blob: 6427406fb19ed0c51ef4ceed178d67778661b669 [file] [log] [blame]
Richard Henderson252b5131999-05-03 07:29:11 +00001/* Alpha specific support for 64-bit ELF
Alan Modra250d07d2021-01-01 09:28:58 +10302 Copyright (C) 1996-2021 Free Software Foundation, Inc.
Richard Henderson252b5131999-05-03 07:29:11 +00003 Contributed by Richard Henderson <rth@tamu.edu>.
4
Nick Clifton571fe012003-01-20 18:06:21 +00005 This file is part of BFD, the Binary File Descriptor library.
Richard Henderson252b5131999-05-03 07:29:11 +00006
Nick Clifton571fe012003-01-20 18:06:21 +00007 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
Nick Cliftoncd123cb2007-07-03 14:26:43 +00009 the Free Software Foundation; either version 3 of the License, or
Nick Clifton571fe012003-01-20 18:06:21 +000010 (at your option) any later version.
Richard Henderson252b5131999-05-03 07:29:11 +000011
Nick Clifton571fe012003-01-20 18:06:21 +000012 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.
Richard Henderson252b5131999-05-03 07:29:11 +000016
Nick Clifton571fe012003-01-20 18:06:21 +000017 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
Nick Cliftoncd123cb2007-07-03 14:26:43 +000019 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
21
Richard Henderson252b5131999-05-03 07:29:11 +000022
23/* We need a published ABI spec for this. Until one comes out, don't
24 assume this'll remain unchanged forever. */
25
Richard Henderson252b5131999-05-03 07:29:11 +000026#include "sysdep.h"
Alan Modra3db64b02007-04-26 14:47:00 +000027#include "bfd.h"
Richard Henderson252b5131999-05-03 07:29:11 +000028#include "libbfd.h"
29#include "elf-bfd.h"
Alan Modra0ba93782019-09-23 10:13:26 +093030#include "ecoff-bfd.h"
Richard Henderson252b5131999-05-03 07:29:11 +000031
32#include "elf/alpha.h"
33
34#define ALPHAECOFF
35
36#define NO_COFF_RELOCS
37#define NO_COFF_SYMBOLS
38#define NO_COFF_LINENOS
39
Kazu Hiratafe8bc632000-12-09 01:54:51 +000040/* Get the ECOFF swapping routines. Needed for the debug information. */
Richard Henderson252b5131999-05-03 07:29:11 +000041#include "coff/internal.h"
42#include "coff/sym.h"
43#include "coff/symconst.h"
44#include "coff/ecoff.h"
45#include "coff/alpha.h"
46#include "aout/ar.h"
47#include "libcoff.h"
48#include "libecoff.h"
49#define ECOFF_64
50#include "ecoffswap.h"
51
Richard Henderson252b5131999-05-03 07:29:11 +000052
Richard Henderson6ec70572005-05-29 23:13:39 +000053/* Instruction data for plt generation and relaxation. */
54
Nick Cliftoneae0b5c2020-08-26 16:26:13 +010055#define OP_LDA 0x08U
56#define OP_LDAH 0x09U
57#define OP_LDQ 0x29U
58#define OP_BR 0x30U
59#define OP_BSR 0x34U
Richard Henderson6ec70572005-05-29 23:13:39 +000060
61#define INSN_LDA (OP_LDA << 26)
62#define INSN_LDAH (OP_LDAH << 26)
63#define INSN_LDQ (OP_LDQ << 26)
64#define INSN_BR (OP_BR << 26)
65
66#define INSN_ADDQ 0x40000400
67#define INSN_RDUNIQ 0x0000009e
68#define INSN_SUBQ 0x40000520
69#define INSN_S4SUBQ 0x40000560
70#define INSN_UNOP 0x2ffe0000
71
72#define INSN_JSR 0x68004000
73#define INSN_JMP 0x68000000
74#define INSN_JSR_MASK 0xfc00c000
75
Nick Cliftoneae0b5c2020-08-26 16:26:13 +010076#define INSN_A(I,A) (I | ((unsigned) A << 21))
77#define INSN_AB(I,A,B) (INSN_A (I, A) | (B << 16))
78#define INSN_ABC(I,A,B,C) (INSN_A (I, A) | (B << 16) | C)
79#define INSN_ABO(I,A,B,O) (INSN_A (I, A) | (B << 16) | ((O) & 0xffff))
80#define INSN_AD(I,A,D) (INSN_A (I, A) | (((D) >> 2) & 0x1fffff))
Richard Henderson6ec70572005-05-29 23:13:39 +000081
82/* PLT/GOT Stuff */
83
84/* Set by ld emulation. Putting this into the link_info or hash structure
85 is simply working too hard. */
86#ifdef USE_SECUREPLT
Alan Modra0a1b45a2021-03-31 10:30:54 +103087bool elf64_alpha_use_secureplt = true;
Richard Henderson6ec70572005-05-29 23:13:39 +000088#else
Alan Modra0a1b45a2021-03-31 10:30:54 +103089bool elf64_alpha_use_secureplt = false;
Richard Henderson6ec70572005-05-29 23:13:39 +000090#endif
91
92#define OLD_PLT_HEADER_SIZE 32
93#define OLD_PLT_ENTRY_SIZE 12
94#define NEW_PLT_HEADER_SIZE 36
95#define NEW_PLT_ENTRY_SIZE 4
96
97#define PLT_HEADER_SIZE \
98 (elf64_alpha_use_secureplt ? NEW_PLT_HEADER_SIZE : OLD_PLT_HEADER_SIZE)
99#define PLT_ENTRY_SIZE \
100 (elf64_alpha_use_secureplt ? NEW_PLT_ENTRY_SIZE : OLD_PLT_ENTRY_SIZE)
101
102#define MAX_GOT_SIZE (64*1024)
103
104#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so"
105
Nick Clifton21d799b2009-09-25 19:13:27 +0000106
107/* Used to implement multiple .got subsections. */
108struct alpha_elf_got_entry
109{
110 struct alpha_elf_got_entry *next;
111
112 /* Which .got subsection? */
113 bfd *gotobj;
114
115 /* The addend in effect for this entry. */
116 bfd_vma addend;
117
118 /* The .got offset for this entry. */
119 int got_offset;
120
121 /* The .plt offset for this entry. */
122 int plt_offset;
123
124 /* How many references to this entry? */
125 int use_count;
126
127 /* The relocation type of this entry. */
128 unsigned char reloc_type;
129
130 /* How a LITERAL is used. */
131 unsigned char flags;
132
133 /* Have we initialized the dynamic relocation for this entry? */
134 unsigned char reloc_done;
135
136 /* Have we adjusted this entry for SEC_MERGE? */
137 unsigned char reloc_xlated;
138};
139
140struct alpha_elf_reloc_entry
141{
142 struct alpha_elf_reloc_entry *next;
143
144 /* Which .reloc section? */
145 asection *srel;
146
H.J. Lu1f7f2ab2020-04-21 05:20:11 -0700147 /* Which section this relocation is against? */
148 asection *sec;
Nick Clifton21d799b2009-09-25 19:13:27 +0000149
150 /* How many did we find? */
151 unsigned long count;
H.J. Lu1f7f2ab2020-04-21 05:20:11 -0700152
153 /* What kind of relocation? */
154 unsigned int rtype;
Nick Clifton21d799b2009-09-25 19:13:27 +0000155};
156
Richard Henderson252b5131999-05-03 07:29:11 +0000157struct alpha_elf_link_hash_entry
158{
159 struct elf_link_hash_entry root;
160
161 /* External symbol information. */
162 EXTR esym;
163
164 /* Cumulative flags for all the .got entries. */
165 int flags;
166
Richard Henderson9e756d62002-06-02 02:28:45 +0000167 /* Contexts in which a literal was referenced. */
Richard Henderson8288a392005-05-31 22:53:44 +0000168#define ALPHA_ELF_LINK_HASH_LU_ADDR 0x01
169#define ALPHA_ELF_LINK_HASH_LU_MEM 0x02
170#define ALPHA_ELF_LINK_HASH_LU_BYTE 0x04
171#define ALPHA_ELF_LINK_HASH_LU_JSR 0x08
172#define ALPHA_ELF_LINK_HASH_LU_TLSGD 0x10
173#define ALPHA_ELF_LINK_HASH_LU_TLSLDM 0x20
174#define ALPHA_ELF_LINK_HASH_LU_JSRDIRECT 0x40
175#define ALPHA_ELF_LINK_HASH_LU_PLT 0x38
176#define ALPHA_ELF_LINK_HASH_TLS_IE 0x80
Richard Hendersoncc03ec82003-01-22 00:47:58 +0000177
Richard Henderson252b5131999-05-03 07:29:11 +0000178 /* Used to implement multiple .got subsections. */
Nick Clifton21d799b2009-09-25 19:13:27 +0000179 struct alpha_elf_got_entry *got_entries;
Richard Henderson252b5131999-05-03 07:29:11 +0000180
Nick Clifton571fe012003-01-20 18:06:21 +0000181 /* Used to count non-got, non-plt relocations for delayed sizing
Richard Henderson252b5131999-05-03 07:29:11 +0000182 of relocation sections. */
Nick Clifton21d799b2009-09-25 19:13:27 +0000183 struct alpha_elf_reloc_entry *reloc_entries;
Richard Henderson252b5131999-05-03 07:29:11 +0000184};
185
186/* Alpha ELF linker hash table. */
187
188struct alpha_elf_link_hash_table
189{
190 struct elf_link_hash_table root;
191
192 /* The head of a list of .got subsections linked through
193 alpha_elf_tdata(abfd)->got_link_next. */
194 bfd *got_list;
Richard Henderson4a828aa2007-04-10 18:00:26 +0000195
196 /* The most recent relax pass that we've seen. The GOTs
197 should be regenerated if this doesn't match. */
198 int relax_trip;
Richard Henderson252b5131999-05-03 07:29:11 +0000199};
200
201/* Look up an entry in a Alpha ELF linker hash table. */
202
203#define alpha_elf_link_hash_lookup(table, string, create, copy, follow) \
204 ((struct alpha_elf_link_hash_entry *) \
205 elf_link_hash_lookup (&(table)->root, (string), (create), \
206 (copy), (follow)))
207
208/* Traverse a Alpha ELF linker hash table. */
209
210#define alpha_elf_link_hash_traverse(table, func, info) \
211 (elf_link_hash_traverse \
212 (&(table)->root, \
Alan Modra0a1b45a2021-03-31 10:30:54 +1030213 (bool (*) (struct elf_link_hash_entry *, void *)) (func), \
Richard Henderson252b5131999-05-03 07:29:11 +0000214 (info)))
215
216/* Get the Alpha ELF linker hash table from a link_info structure. */
217
218#define alpha_elf_hash_table(p) \
Alan Modra0f553202020-08-25 02:37:02 +0930219 ((is_elf_hash_table ((p)->hash) \
220 && elf_hash_table_id (elf_hash_table (p)) == ALPHA_ELF_DATA) \
221 ? (struct alpha_elf_link_hash_table *) (p)->hash : NULL)
Richard Henderson252b5131999-05-03 07:29:11 +0000222
223/* Get the object's symbols as our own entry type. */
224
225#define alpha_elf_sym_hashes(abfd) \
226 ((struct alpha_elf_link_hash_entry **)elf_sym_hashes(abfd))
227
H.J. Lu68ffbac2013-01-10 20:03:55 +0000228/* Should we do dynamic things to this symbol? This differs from the
Richard Henderson986a2412003-07-18 21:09:28 +0000229 generic version in that we never need to consider function pointer
230 equality wrt PLT entries -- we don't create a PLT entry if a symbol's
231 address is ever taken. */
Richard Henderson252b5131999-05-03 07:29:11 +0000232
Alan Modra0a1b45a2021-03-31 10:30:54 +1030233static inline bool
Richard Hendersona7519a32005-05-26 07:14:03 +0000234alpha_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
235 struct bfd_link_info *info)
Richard Henderson8fb35fe2001-01-27 00:04:09 +0000236{
Richard Henderson986a2412003-07-18 21:09:28 +0000237 return _bfd_elf_dynamic_symbol_p (h, info, 0);
Richard Henderson8fb35fe2001-01-27 00:04:09 +0000238}
Richard Henderson252b5131999-05-03 07:29:11 +0000239
240/* Create an entry in a Alpha ELF linker hash table. */
241
242static struct bfd_hash_entry *
Richard Hendersona7519a32005-05-26 07:14:03 +0000243elf64_alpha_link_hash_newfunc (struct bfd_hash_entry *entry,
244 struct bfd_hash_table *table,
245 const char *string)
Richard Henderson252b5131999-05-03 07:29:11 +0000246{
247 struct alpha_elf_link_hash_entry *ret =
248 (struct alpha_elf_link_hash_entry *) entry;
249
250 /* Allocate the structure if it has not already been allocated by a
251 subclass. */
252 if (ret == (struct alpha_elf_link_hash_entry *) NULL)
253 ret = ((struct alpha_elf_link_hash_entry *)
254 bfd_hash_allocate (table,
255 sizeof (struct alpha_elf_link_hash_entry)));
256 if (ret == (struct alpha_elf_link_hash_entry *) NULL)
257 return (struct bfd_hash_entry *) ret;
258
259 /* Call the allocation method of the superclass. */
260 ret = ((struct alpha_elf_link_hash_entry *)
261 _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
262 table, string));
263 if (ret != (struct alpha_elf_link_hash_entry *) NULL)
264 {
265 /* Set local fields. */
266 memset (&ret->esym, 0, sizeof (EXTR));
267 /* We use -2 as a marker to indicate that the information has
268 not been set. -1 means there is no associated ifd. */
269 ret->esym.ifd = -2;
270 ret->flags = 0;
271 ret->got_entries = NULL;
272 ret->reloc_entries = NULL;
273 }
274
275 return (struct bfd_hash_entry *) ret;
276}
277
278/* Create a Alpha ELF linker hash table. */
279
280static struct bfd_link_hash_table *
Richard Hendersona7519a32005-05-26 07:14:03 +0000281elf64_alpha_bfd_link_hash_table_create (bfd *abfd)
Richard Henderson252b5131999-05-03 07:29:11 +0000282{
283 struct alpha_elf_link_hash_table *ret;
Alan Modra986f0782020-02-19 13:12:00 +1030284 size_t amt = sizeof (struct alpha_elf_link_hash_table);
Richard Henderson252b5131999-05-03 07:29:11 +0000285
Daniel Jacobowitze2d34d72002-04-04 19:53:38 +0000286 ret = (struct alpha_elf_link_hash_table *) bfd_zmalloc (amt);
Richard Henderson252b5131999-05-03 07:29:11 +0000287 if (ret == (struct alpha_elf_link_hash_table *) NULL)
288 return NULL;
289
Alan Modra66eb6682006-03-16 12:20:16 +0000290 if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
291 elf64_alpha_link_hash_newfunc,
Nick Clifton4dfe6ac2010-02-04 09:16:43 +0000292 sizeof (struct alpha_elf_link_hash_entry),
293 ALPHA_ELF_DATA))
Richard Henderson252b5131999-05-03 07:29:11 +0000294 {
Daniel Jacobowitze2d34d72002-04-04 19:53:38 +0000295 free (ret);
Richard Henderson252b5131999-05-03 07:29:11 +0000296 return NULL;
297 }
298
299 return &ret->root.root;
300}
301
Alan Modra698600e2013-02-18 02:56:58 +0000302/* Alpha ELF follows MIPS ELF in using a special find_nearest_line
303 routine in order to handle the ECOFF debugging information. */
304
305struct alpha_elf_find_line
306{
307 struct ecoff_debug_info d;
308 struct ecoff_find_line i;
309};
310
Richard Henderson252b5131999-05-03 07:29:11 +0000311/* We have some private fields hanging off of the elf_tdata structure. */
312
313struct alpha_elf_obj_tdata
314{
315 struct elf_obj_tdata root;
316
317 /* For every input file, these are the got entries for that object's
318 local symbols. */
319 struct alpha_elf_got_entry ** local_got_entries;
320
321 /* For every input file, this is the object that owns the got that
322 this input file uses. */
323 bfd *gotobj;
324
325 /* For every got, this is a linked list through the objects using this got */
326 bfd *in_got_link_next;
327
328 /* For every got, this is a link to the next got subsegment. */
329 bfd *got_link_next;
330
331 /* For every got, this is the section. */
332 asection *got;
333
Richard Henderson3765b1b2002-05-30 22:01:38 +0000334 /* For every got, this is it's total number of words. */
335 int total_got_size;
Richard Henderson252b5131999-05-03 07:29:11 +0000336
Richard Henderson3765b1b2002-05-30 22:01:38 +0000337 /* For every got, this is the sum of the number of words required
Richard Henderson252b5131999-05-03 07:29:11 +0000338 to hold all of the member object's local got. */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000339 int local_got_size;
Alan Modra698600e2013-02-18 02:56:58 +0000340
341 /* Used by elf64_alpha_find_nearest_line entry point. */
342 struct alpha_elf_find_line *find_line_info;
343
Richard Henderson252b5131999-05-03 07:29:11 +0000344};
345
346#define alpha_elf_tdata(abfd) \
347 ((struct alpha_elf_obj_tdata *) (abfd)->tdata.any)
348
Nick Clifton0ffa91d2008-02-12 11:32:31 +0000349#define is_alpha_elf(bfd) \
350 (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
351 && elf_tdata (bfd) != NULL \
Nick Clifton4dfe6ac2010-02-04 09:16:43 +0000352 && elf_object_id (bfd) == ALPHA_ELF_DATA)
Nick Clifton0ffa91d2008-02-12 11:32:31 +0000353
Alan Modra0a1b45a2021-03-31 10:30:54 +1030354static bool
Richard Hendersona7519a32005-05-26 07:14:03 +0000355elf64_alpha_mkobject (bfd *abfd)
Richard Henderson252b5131999-05-03 07:29:11 +0000356{
Nick Clifton0ffa91d2008-02-12 11:32:31 +0000357 return bfd_elf_allocate_object (abfd, sizeof (struct alpha_elf_obj_tdata),
Nick Clifton4dfe6ac2010-02-04 09:16:43 +0000358 ALPHA_ELF_DATA);
Richard Henderson252b5131999-05-03 07:29:11 +0000359}
360
Alan Modra0a1b45a2021-03-31 10:30:54 +1030361static bool
Richard Hendersona7519a32005-05-26 07:14:03 +0000362elf64_alpha_object_p (bfd *abfd)
Richard Henderson252b5131999-05-03 07:29:11 +0000363{
Richard Henderson252b5131999-05-03 07:29:11 +0000364 /* Set the right machine number for an Alpha ELF file. */
365 return bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0);
366}
367
Richard Hendersona7519a32005-05-26 07:14:03 +0000368/* A relocation function which doesn't do anything. */
369
370static bfd_reloc_status_type
371elf64_alpha_reloc_nil (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc,
372 asymbol *sym ATTRIBUTE_UNUSED,
Nick Clifton2c3fc382012-07-13 14:22:50 +0000373 void * data ATTRIBUTE_UNUSED, asection *sec,
Richard Hendersona7519a32005-05-26 07:14:03 +0000374 bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED)
375{
376 if (output_bfd)
377 reloc->address += sec->output_offset;
378 return bfd_reloc_ok;
379}
380
381/* A relocation function used for an unsupported reloc. */
382
383static bfd_reloc_status_type
384elf64_alpha_reloc_bad (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc,
385 asymbol *sym ATTRIBUTE_UNUSED,
Nick Clifton2c3fc382012-07-13 14:22:50 +0000386 void * data ATTRIBUTE_UNUSED, asection *sec,
Richard Hendersona7519a32005-05-26 07:14:03 +0000387 bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED)
388{
389 if (output_bfd)
390 reloc->address += sec->output_offset;
391 return bfd_reloc_notsupported;
392}
393
394/* Do the work of the GPDISP relocation. */
395
396static bfd_reloc_status_type
397elf64_alpha_do_reloc_gpdisp (bfd *abfd, bfd_vma gpdisp, bfd_byte *p_ldah,
398 bfd_byte *p_lda)
399{
400 bfd_reloc_status_type ret = bfd_reloc_ok;
401 bfd_vma addend;
402 unsigned long i_ldah, i_lda;
403
404 i_ldah = bfd_get_32 (abfd, p_ldah);
405 i_lda = bfd_get_32 (abfd, p_lda);
406
407 /* Complain if the instructions are not correct. */
408 if (((i_ldah >> 26) & 0x3f) != 0x09
409 || ((i_lda >> 26) & 0x3f) != 0x08)
410 ret = bfd_reloc_dangerous;
411
412 /* Extract the user-supplied offset, mirroring the sign extensions
413 that the instructions perform. */
414 addend = ((i_ldah & 0xffff) << 16) | (i_lda & 0xffff);
415 addend = (addend ^ 0x80008000) - 0x80008000;
416
417 gpdisp += addend;
418
419 if ((bfd_signed_vma) gpdisp < -(bfd_signed_vma) 0x80000000
420 || (bfd_signed_vma) gpdisp >= (bfd_signed_vma) 0x7fff8000)
421 ret = bfd_reloc_overflow;
422
423 /* compensate for the sign extension again. */
424 i_ldah = ((i_ldah & 0xffff0000)
425 | (((gpdisp >> 16) + ((gpdisp >> 15) & 1)) & 0xffff));
426 i_lda = (i_lda & 0xffff0000) | (gpdisp & 0xffff);
427
428 bfd_put_32 (abfd, (bfd_vma) i_ldah, p_ldah);
429 bfd_put_32 (abfd, (bfd_vma) i_lda, p_lda);
430
431 return ret;
432}
433
434/* The special function for the GPDISP reloc. */
435
436static bfd_reloc_status_type
437elf64_alpha_reloc_gpdisp (bfd *abfd, arelent *reloc_entry,
Nick Clifton2c3fc382012-07-13 14:22:50 +0000438 asymbol *sym ATTRIBUTE_UNUSED, void * data,
Richard Hendersona7519a32005-05-26 07:14:03 +0000439 asection *input_section, bfd *output_bfd,
440 char **err_msg)
441{
442 bfd_reloc_status_type ret;
443 bfd_vma gp, relocation;
444 bfd_vma high_address;
445 bfd_byte *p_ldah, *p_lda;
446
447 /* Don't do anything if we're not doing a final link. */
448 if (output_bfd)
449 {
450 reloc_entry->address += input_section->output_offset;
451 return bfd_reloc_ok;
452 }
453
454 high_address = bfd_get_section_limit (abfd, input_section);
455 if (reloc_entry->address > high_address
456 || reloc_entry->address + reloc_entry->addend > high_address)
457 return bfd_reloc_outofrange;
458
459 /* The gp used in the portion of the output object to which this
460 input object belongs is cached on the input bfd. */
461 gp = _bfd_get_gp_value (abfd);
462
463 relocation = (input_section->output_section->vma
464 + input_section->output_offset
465 + reloc_entry->address);
466
467 p_ldah = (bfd_byte *) data + reloc_entry->address;
468 p_lda = p_ldah + reloc_entry->addend;
469
470 ret = elf64_alpha_do_reloc_gpdisp (abfd, gp - relocation, p_ldah, p_lda);
471
472 /* Complain if the instructions are not correct. */
473 if (ret == bfd_reloc_dangerous)
474 *err_msg = _("GPDISP relocation did not find ldah and lda instructions");
475
476 return ret;
477}
478
Richard Henderson252b5131999-05-03 07:29:11 +0000479/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
480 from smaller values. Start with zero, widen, *then* decrement. */
481#define MINUS_ONE (((bfd_vma)0) - 1)
482
Nick Clifton21d799b2009-09-25 19:13:27 +0000483
Richard Hendersondfe57ca2001-09-05 03:00:14 +0000484#define SKIP_HOWTO(N) \
Nick Clifton21d799b2009-09-25 19:13:27 +0000485 HOWTO(N, 0, 0, 0, 0, 0, complain_overflow_dont, elf64_alpha_reloc_bad, 0, 0, 0, 0, 0)
Richard Hendersondfe57ca2001-09-05 03:00:14 +0000486
Richard Henderson252b5131999-05-03 07:29:11 +0000487static reloc_howto_type elf64_alpha_howto_table[] =
488{
489 HOWTO (R_ALPHA_NONE, /* type */
490 0, /* rightshift */
Alan Modra6346d5c2015-01-19 10:36:26 +1030491 3, /* size (0 = byte, 1 = short, 2 = long) */
492 0, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030493 true, /* pc_relative */
Richard Henderson252b5131999-05-03 07:29:11 +0000494 0, /* bitpos */
495 complain_overflow_dont, /* complain_on_overflow */
496 elf64_alpha_reloc_nil, /* special_function */
497 "NONE", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030498 false, /* partial_inplace */
Richard Henderson252b5131999-05-03 07:29:11 +0000499 0, /* src_mask */
500 0, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030501 true), /* pcrel_offset */
Richard Henderson252b5131999-05-03 07:29:11 +0000502
503 /* A 32 bit reference to a symbol. */
504 HOWTO (R_ALPHA_REFLONG, /* type */
505 0, /* rightshift */
506 2, /* size (0 = byte, 1 = short, 2 = long) */
507 32, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030508 false, /* pc_relative */
Richard Henderson252b5131999-05-03 07:29:11 +0000509 0, /* bitpos */
510 complain_overflow_bitfield, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000511 bfd_elf_generic_reloc, /* special_function */
Richard Henderson252b5131999-05-03 07:29:11 +0000512 "REFLONG", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030513 false, /* partial_inplace */
Richard Henderson252b5131999-05-03 07:29:11 +0000514 0xffffffff, /* src_mask */
515 0xffffffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030516 false), /* pcrel_offset */
Richard Henderson252b5131999-05-03 07:29:11 +0000517
518 /* A 64 bit reference to a symbol. */
519 HOWTO (R_ALPHA_REFQUAD, /* type */
520 0, /* rightshift */
521 4, /* size (0 = byte, 1 = short, 2 = long) */
522 64, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030523 false, /* pc_relative */
Richard Henderson252b5131999-05-03 07:29:11 +0000524 0, /* bitpos */
525 complain_overflow_bitfield, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000526 bfd_elf_generic_reloc, /* special_function */
Richard Henderson252b5131999-05-03 07:29:11 +0000527 "REFQUAD", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030528 false, /* partial_inplace */
Richard Henderson252b5131999-05-03 07:29:11 +0000529 MINUS_ONE, /* src_mask */
530 MINUS_ONE, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030531 false), /* pcrel_offset */
Richard Henderson252b5131999-05-03 07:29:11 +0000532
533 /* A 32 bit GP relative offset. This is just like REFLONG except
534 that when the value is used the value of the gp register will be
535 added in. */
536 HOWTO (R_ALPHA_GPREL32, /* type */
537 0, /* rightshift */
538 2, /* size (0 = byte, 1 = short, 2 = long) */
539 32, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030540 false, /* pc_relative */
Richard Henderson252b5131999-05-03 07:29:11 +0000541 0, /* bitpos */
542 complain_overflow_bitfield, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000543 bfd_elf_generic_reloc, /* special_function */
Richard Henderson252b5131999-05-03 07:29:11 +0000544 "GPREL32", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030545 false, /* partial_inplace */
Richard Henderson252b5131999-05-03 07:29:11 +0000546 0xffffffff, /* src_mask */
547 0xffffffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030548 false), /* pcrel_offset */
Richard Henderson252b5131999-05-03 07:29:11 +0000549
550 /* Used for an instruction that refers to memory off the GP register. */
551 HOWTO (R_ALPHA_LITERAL, /* type */
552 0, /* rightshift */
Richard Hendersondfe57ca2001-09-05 03:00:14 +0000553 1, /* size (0 = byte, 1 = short, 2 = long) */
Richard Henderson252b5131999-05-03 07:29:11 +0000554 16, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030555 false, /* pc_relative */
Richard Henderson252b5131999-05-03 07:29:11 +0000556 0, /* bitpos */
557 complain_overflow_signed, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000558 bfd_elf_generic_reloc, /* special_function */
Richard Henderson252b5131999-05-03 07:29:11 +0000559 "ELF_LITERAL", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030560 false, /* partial_inplace */
Richard Henderson252b5131999-05-03 07:29:11 +0000561 0xffff, /* src_mask */
562 0xffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030563 false), /* pcrel_offset */
Richard Henderson252b5131999-05-03 07:29:11 +0000564
565 /* This reloc only appears immediately following an ELF_LITERAL reloc.
566 It identifies a use of the literal. The symbol index is special:
567 1 means the literal address is in the base register of a memory
568 format instruction; 2 means the literal address is in the byte
569 offset register of a byte-manipulation instruction; 3 means the
570 literal address is in the target register of a jsr instruction.
571 This does not actually do any relocation. */
572 HOWTO (R_ALPHA_LITUSE, /* type */
573 0, /* rightshift */
Richard Hendersondfe57ca2001-09-05 03:00:14 +0000574 1, /* size (0 = byte, 1 = short, 2 = long) */
Richard Henderson252b5131999-05-03 07:29:11 +0000575 32, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030576 false, /* pc_relative */
Richard Henderson252b5131999-05-03 07:29:11 +0000577 0, /* bitpos */
578 complain_overflow_dont, /* complain_on_overflow */
579 elf64_alpha_reloc_nil, /* special_function */
580 "LITUSE", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030581 false, /* partial_inplace */
Richard Henderson252b5131999-05-03 07:29:11 +0000582 0, /* src_mask */
583 0, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030584 false), /* pcrel_offset */
Richard Henderson252b5131999-05-03 07:29:11 +0000585
586 /* Load the gp register. This is always used for a ldah instruction
587 which loads the upper 16 bits of the gp register. The symbol
588 index of the GPDISP instruction is an offset in bytes to the lda
589 instruction that loads the lower 16 bits. The value to use for
590 the relocation is the difference between the GP value and the
591 current location; the load will always be done against a register
592 holding the current address.
593
594 NOTE: Unlike ECOFF, partial in-place relocation is not done. If
595 any offset is present in the instructions, it is an offset from
596 the register to the ldah instruction. This lets us avoid any
597 stupid hackery like inventing a gp value to do partial relocation
598 against. Also unlike ECOFF, we do the whole relocation off of
599 the GPDISP rather than a GPDISP_HI16/GPDISP_LO16 pair. An odd,
600 space consuming bit, that, since all the information was present
601 in the GPDISP_HI16 reloc. */
602 HOWTO (R_ALPHA_GPDISP, /* type */
603 16, /* rightshift */
604 2, /* size (0 = byte, 1 = short, 2 = long) */
605 16, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030606 false, /* pc_relative */
Richard Henderson252b5131999-05-03 07:29:11 +0000607 0, /* bitpos */
608 complain_overflow_dont, /* complain_on_overflow */
609 elf64_alpha_reloc_gpdisp, /* special_function */
610 "GPDISP", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030611 false, /* partial_inplace */
Richard Henderson252b5131999-05-03 07:29:11 +0000612 0xffff, /* src_mask */
613 0xffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030614 true), /* pcrel_offset */
Richard Henderson252b5131999-05-03 07:29:11 +0000615
616 /* A 21 bit branch. */
617 HOWTO (R_ALPHA_BRADDR, /* type */
618 2, /* rightshift */
619 2, /* size (0 = byte, 1 = short, 2 = long) */
620 21, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030621 true, /* pc_relative */
Richard Henderson252b5131999-05-03 07:29:11 +0000622 0, /* bitpos */
623 complain_overflow_signed, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000624 bfd_elf_generic_reloc, /* special_function */
Richard Henderson252b5131999-05-03 07:29:11 +0000625 "BRADDR", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030626 false, /* partial_inplace */
Richard Henderson252b5131999-05-03 07:29:11 +0000627 0x1fffff, /* src_mask */
628 0x1fffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030629 true), /* pcrel_offset */
Richard Henderson252b5131999-05-03 07:29:11 +0000630
631 /* A hint for a jump to a register. */
632 HOWTO (R_ALPHA_HINT, /* type */
633 2, /* rightshift */
Richard Hendersondfe57ca2001-09-05 03:00:14 +0000634 1, /* size (0 = byte, 1 = short, 2 = long) */
Richard Henderson252b5131999-05-03 07:29:11 +0000635 14, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030636 true, /* pc_relative */
Richard Henderson252b5131999-05-03 07:29:11 +0000637 0, /* bitpos */
638 complain_overflow_dont, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000639 bfd_elf_generic_reloc, /* special_function */
Richard Henderson252b5131999-05-03 07:29:11 +0000640 "HINT", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030641 false, /* partial_inplace */
Richard Henderson252b5131999-05-03 07:29:11 +0000642 0x3fff, /* src_mask */
643 0x3fff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030644 true), /* pcrel_offset */
Richard Henderson252b5131999-05-03 07:29:11 +0000645
646 /* 16 bit PC relative offset. */
647 HOWTO (R_ALPHA_SREL16, /* type */
648 0, /* rightshift */
649 1, /* size (0 = byte, 1 = short, 2 = long) */
650 16, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030651 true, /* pc_relative */
Richard Henderson252b5131999-05-03 07:29:11 +0000652 0, /* bitpos */
653 complain_overflow_signed, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000654 bfd_elf_generic_reloc, /* special_function */
Richard Henderson252b5131999-05-03 07:29:11 +0000655 "SREL16", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030656 false, /* partial_inplace */
Richard Henderson252b5131999-05-03 07:29:11 +0000657 0xffff, /* src_mask */
658 0xffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030659 true), /* pcrel_offset */
Richard Henderson252b5131999-05-03 07:29:11 +0000660
661 /* 32 bit PC relative offset. */
662 HOWTO (R_ALPHA_SREL32, /* type */
663 0, /* rightshift */
664 2, /* size (0 = byte, 1 = short, 2 = long) */
665 32, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030666 true, /* pc_relative */
Richard Henderson252b5131999-05-03 07:29:11 +0000667 0, /* bitpos */
668 complain_overflow_signed, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000669 bfd_elf_generic_reloc, /* special_function */
Richard Henderson252b5131999-05-03 07:29:11 +0000670 "SREL32", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030671 false, /* partial_inplace */
Richard Henderson252b5131999-05-03 07:29:11 +0000672 0xffffffff, /* src_mask */
673 0xffffffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030674 true), /* pcrel_offset */
Richard Henderson252b5131999-05-03 07:29:11 +0000675
676 /* A 64 bit PC relative offset. */
677 HOWTO (R_ALPHA_SREL64, /* type */
678 0, /* rightshift */
679 4, /* size (0 = byte, 1 = short, 2 = long) */
680 64, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030681 true, /* pc_relative */
Richard Henderson252b5131999-05-03 07:29:11 +0000682 0, /* bitpos */
683 complain_overflow_signed, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000684 bfd_elf_generic_reloc, /* special_function */
Richard Henderson252b5131999-05-03 07:29:11 +0000685 "SREL64", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030686 false, /* partial_inplace */
Richard Henderson252b5131999-05-03 07:29:11 +0000687 MINUS_ONE, /* src_mask */
688 MINUS_ONE, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030689 true), /* pcrel_offset */
Richard Henderson252b5131999-05-03 07:29:11 +0000690
Richard Hendersondfe57ca2001-09-05 03:00:14 +0000691 /* Skip 12 - 16; deprecated ECOFF relocs. */
692 SKIP_HOWTO (12),
693 SKIP_HOWTO (13),
694 SKIP_HOWTO (14),
695 SKIP_HOWTO (15),
696 SKIP_HOWTO (16),
Richard Henderson252b5131999-05-03 07:29:11 +0000697
698 /* The high 16 bits of the displacement from GP to the target. */
699 HOWTO (R_ALPHA_GPRELHIGH,
700 0, /* rightshift */
Richard Hendersondfe57ca2001-09-05 03:00:14 +0000701 1, /* size (0 = byte, 1 = short, 2 = long) */
Richard Henderson252b5131999-05-03 07:29:11 +0000702 16, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030703 false, /* pc_relative */
Richard Henderson252b5131999-05-03 07:29:11 +0000704 0, /* bitpos */
705 complain_overflow_signed, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000706 bfd_elf_generic_reloc, /* special_function */
Richard Henderson252b5131999-05-03 07:29:11 +0000707 "GPRELHIGH", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030708 false, /* partial_inplace */
Richard Henderson252b5131999-05-03 07:29:11 +0000709 0xffff, /* src_mask */
710 0xffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030711 false), /* pcrel_offset */
Richard Henderson252b5131999-05-03 07:29:11 +0000712
713 /* The low 16 bits of the displacement from GP to the target. */
714 HOWTO (R_ALPHA_GPRELLOW,
715 0, /* rightshift */
Richard Hendersondfe57ca2001-09-05 03:00:14 +0000716 1, /* size (0 = byte, 1 = short, 2 = long) */
Richard Henderson252b5131999-05-03 07:29:11 +0000717 16, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030718 false, /* pc_relative */
Richard Henderson252b5131999-05-03 07:29:11 +0000719 0, /* bitpos */
720 complain_overflow_dont, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000721 bfd_elf_generic_reloc, /* special_function */
Richard Henderson252b5131999-05-03 07:29:11 +0000722 "GPRELLOW", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030723 false, /* partial_inplace */
Richard Henderson252b5131999-05-03 07:29:11 +0000724 0xffff, /* src_mask */
725 0xffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030726 false), /* pcrel_offset */
Richard Henderson252b5131999-05-03 07:29:11 +0000727
728 /* A 16-bit displacement from the GP to the target. */
Richard Hendersondfe57ca2001-09-05 03:00:14 +0000729 HOWTO (R_ALPHA_GPREL16,
Richard Henderson252b5131999-05-03 07:29:11 +0000730 0, /* rightshift */
Richard Hendersondfe57ca2001-09-05 03:00:14 +0000731 1, /* size (0 = byte, 1 = short, 2 = long) */
Richard Henderson252b5131999-05-03 07:29:11 +0000732 16, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030733 false, /* pc_relative */
Richard Henderson252b5131999-05-03 07:29:11 +0000734 0, /* bitpos */
735 complain_overflow_signed, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000736 bfd_elf_generic_reloc, /* special_function */
Richard Hendersondfe57ca2001-09-05 03:00:14 +0000737 "GPREL16", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030738 false, /* partial_inplace */
Richard Henderson252b5131999-05-03 07:29:11 +0000739 0xffff, /* src_mask */
740 0xffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030741 false), /* pcrel_offset */
Richard Henderson252b5131999-05-03 07:29:11 +0000742
Richard Hendersondfe57ca2001-09-05 03:00:14 +0000743 /* Skip 20 - 23; deprecated ECOFF relocs. */
744 SKIP_HOWTO (20),
745 SKIP_HOWTO (21),
746 SKIP_HOWTO (22),
747 SKIP_HOWTO (23),
Richard Henderson252b5131999-05-03 07:29:11 +0000748
Kazu Hiratafe8bc632000-12-09 01:54:51 +0000749 /* Misc ELF relocations. */
Richard Henderson252b5131999-05-03 07:29:11 +0000750
751 /* A dynamic relocation to copy the target into our .dynbss section. */
752 /* Not generated, as all Alpha objects use PIC, so it is not needed. It
753 is present because every other ELF has one, but should not be used
754 because .dynbss is an ugly thing. */
755 HOWTO (R_ALPHA_COPY,
756 0,
757 0,
758 0,
Alan Modra0a1b45a2021-03-31 10:30:54 +1030759 false,
Richard Henderson252b5131999-05-03 07:29:11 +0000760 0,
761 complain_overflow_dont,
762 bfd_elf_generic_reloc,
763 "COPY",
Alan Modra0a1b45a2021-03-31 10:30:54 +1030764 false,
Richard Henderson252b5131999-05-03 07:29:11 +0000765 0,
766 0,
Alan Modra0a1b45a2021-03-31 10:30:54 +1030767 true),
Richard Henderson252b5131999-05-03 07:29:11 +0000768
769 /* A dynamic relocation for a .got entry. */
770 HOWTO (R_ALPHA_GLOB_DAT,
771 0,
772 0,
773 0,
Alan Modra0a1b45a2021-03-31 10:30:54 +1030774 false,
Richard Henderson252b5131999-05-03 07:29:11 +0000775 0,
776 complain_overflow_dont,
777 bfd_elf_generic_reloc,
778 "GLOB_DAT",
Alan Modra0a1b45a2021-03-31 10:30:54 +1030779 false,
Richard Henderson252b5131999-05-03 07:29:11 +0000780 0,
781 0,
Alan Modra0a1b45a2021-03-31 10:30:54 +1030782 true),
Richard Henderson252b5131999-05-03 07:29:11 +0000783
784 /* A dynamic relocation for a .plt entry. */
785 HOWTO (R_ALPHA_JMP_SLOT,
786 0,
787 0,
788 0,
Alan Modra0a1b45a2021-03-31 10:30:54 +1030789 false,
Richard Henderson252b5131999-05-03 07:29:11 +0000790 0,
791 complain_overflow_dont,
792 bfd_elf_generic_reloc,
793 "JMP_SLOT",
Alan Modra0a1b45a2021-03-31 10:30:54 +1030794 false,
Richard Henderson252b5131999-05-03 07:29:11 +0000795 0,
796 0,
Alan Modra0a1b45a2021-03-31 10:30:54 +1030797 true),
Richard Henderson252b5131999-05-03 07:29:11 +0000798
799 /* A dynamic relocation to add the base of the DSO to a 64-bit field. */
800 HOWTO (R_ALPHA_RELATIVE,
801 0,
802 0,
803 0,
Alan Modra0a1b45a2021-03-31 10:30:54 +1030804 false,
Richard Henderson252b5131999-05-03 07:29:11 +0000805 0,
806 complain_overflow_dont,
807 bfd_elf_generic_reloc,
808 "RELATIVE",
Alan Modra0a1b45a2021-03-31 10:30:54 +1030809 false,
Richard Henderson252b5131999-05-03 07:29:11 +0000810 0,
811 0,
Alan Modra0a1b45a2021-03-31 10:30:54 +1030812 true),
Richard Henderson7793f4d2002-02-09 22:53:53 +0000813
814 /* A 21 bit branch that adjusts for gp loads. */
815 HOWTO (R_ALPHA_BRSGP, /* type */
816 2, /* rightshift */
817 2, /* size (0 = byte, 1 = short, 2 = long) */
818 21, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030819 true, /* pc_relative */
Richard Henderson7793f4d2002-02-09 22:53:53 +0000820 0, /* bitpos */
821 complain_overflow_signed, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000822 bfd_elf_generic_reloc, /* special_function */
Richard Henderson7793f4d2002-02-09 22:53:53 +0000823 "BRSGP", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030824 false, /* partial_inplace */
Richard Henderson7793f4d2002-02-09 22:53:53 +0000825 0x1fffff, /* src_mask */
826 0x1fffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030827 true), /* pcrel_offset */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000828
829 /* Creates a tls_index for the symbol in the got. */
830 HOWTO (R_ALPHA_TLSGD, /* type */
831 0, /* rightshift */
832 1, /* size (0 = byte, 1 = short, 2 = long) */
833 16, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030834 false, /* pc_relative */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000835 0, /* bitpos */
836 complain_overflow_signed, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000837 bfd_elf_generic_reloc, /* special_function */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000838 "TLSGD", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030839 false, /* partial_inplace */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000840 0xffff, /* src_mask */
841 0xffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030842 false), /* pcrel_offset */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000843
844 /* Creates a tls_index for the (current) module in the got. */
845 HOWTO (R_ALPHA_TLSLDM, /* type */
846 0, /* rightshift */
847 1, /* size (0 = byte, 1 = short, 2 = long) */
848 16, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030849 false, /* pc_relative */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000850 0, /* bitpos */
851 complain_overflow_signed, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000852 bfd_elf_generic_reloc, /* special_function */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000853 "TLSLDM", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030854 false, /* partial_inplace */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000855 0xffff, /* src_mask */
856 0xffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030857 false), /* pcrel_offset */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000858
859 /* A dynamic relocation for a DTP module entry. */
860 HOWTO (R_ALPHA_DTPMOD64, /* type */
861 0, /* rightshift */
862 4, /* size (0 = byte, 1 = short, 2 = long) */
863 64, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030864 false, /* pc_relative */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000865 0, /* bitpos */
866 complain_overflow_bitfield, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000867 bfd_elf_generic_reloc, /* special_function */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000868 "DTPMOD64", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030869 false, /* partial_inplace */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000870 MINUS_ONE, /* src_mask */
871 MINUS_ONE, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030872 false), /* pcrel_offset */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000873
874 /* Creates a 64-bit offset in the got for the displacement
875 from DTP to the target. */
876 HOWTO (R_ALPHA_GOTDTPREL, /* type */
877 0, /* rightshift */
878 1, /* size (0 = byte, 1 = short, 2 = long) */
879 16, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030880 false, /* pc_relative */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000881 0, /* bitpos */
882 complain_overflow_signed, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000883 bfd_elf_generic_reloc, /* special_function */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000884 "GOTDTPREL", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030885 false, /* partial_inplace */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000886 0xffff, /* src_mask */
887 0xffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030888 false), /* pcrel_offset */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000889
890 /* A dynamic relocation for a displacement from DTP to the target. */
891 HOWTO (R_ALPHA_DTPREL64, /* type */
892 0, /* rightshift */
893 4, /* size (0 = byte, 1 = short, 2 = long) */
894 64, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030895 false, /* pc_relative */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000896 0, /* bitpos */
897 complain_overflow_bitfield, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000898 bfd_elf_generic_reloc, /* special_function */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000899 "DTPREL64", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030900 false, /* partial_inplace */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000901 MINUS_ONE, /* src_mask */
902 MINUS_ONE, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030903 false), /* pcrel_offset */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000904
905 /* The high 16 bits of the displacement from DTP to the target. */
906 HOWTO (R_ALPHA_DTPRELHI, /* type */
907 0, /* rightshift */
908 1, /* size (0 = byte, 1 = short, 2 = long) */
909 16, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030910 false, /* pc_relative */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000911 0, /* bitpos */
912 complain_overflow_signed, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000913 bfd_elf_generic_reloc, /* special_function */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000914 "DTPRELHI", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030915 false, /* partial_inplace */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000916 0xffff, /* src_mask */
917 0xffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030918 false), /* pcrel_offset */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000919
920 /* The low 16 bits of the displacement from DTP to the target. */
921 HOWTO (R_ALPHA_DTPRELLO, /* type */
922 0, /* rightshift */
923 1, /* size (0 = byte, 1 = short, 2 = long) */
924 16, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030925 false, /* pc_relative */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000926 0, /* bitpos */
927 complain_overflow_dont, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000928 bfd_elf_generic_reloc, /* special_function */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000929 "DTPRELLO", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030930 false, /* partial_inplace */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000931 0xffff, /* src_mask */
932 0xffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030933 false), /* pcrel_offset */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000934
935 /* A 16-bit displacement from DTP to the target. */
936 HOWTO (R_ALPHA_DTPREL16, /* type */
937 0, /* rightshift */
938 1, /* size (0 = byte, 1 = short, 2 = long) */
939 16, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030940 false, /* pc_relative */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000941 0, /* bitpos */
942 complain_overflow_signed, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000943 bfd_elf_generic_reloc, /* special_function */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000944 "DTPREL16", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030945 false, /* partial_inplace */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000946 0xffff, /* src_mask */
947 0xffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030948 false), /* pcrel_offset */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000949
950 /* Creates a 64-bit offset in the got for the displacement
951 from TP to the target. */
952 HOWTO (R_ALPHA_GOTTPREL, /* type */
953 0, /* rightshift */
954 1, /* size (0 = byte, 1 = short, 2 = long) */
955 16, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030956 false, /* pc_relative */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000957 0, /* bitpos */
958 complain_overflow_signed, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000959 bfd_elf_generic_reloc, /* special_function */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000960 "GOTTPREL", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030961 false, /* partial_inplace */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000962 0xffff, /* src_mask */
963 0xffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030964 false), /* pcrel_offset */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000965
966 /* A dynamic relocation for a displacement from TP to the target. */
967 HOWTO (R_ALPHA_TPREL64, /* type */
968 0, /* rightshift */
969 4, /* size (0 = byte, 1 = short, 2 = long) */
970 64, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030971 false, /* pc_relative */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000972 0, /* bitpos */
973 complain_overflow_bitfield, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000974 bfd_elf_generic_reloc, /* special_function */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000975 "TPREL64", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030976 false, /* partial_inplace */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000977 MINUS_ONE, /* src_mask */
978 MINUS_ONE, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030979 false), /* pcrel_offset */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000980
981 /* The high 16 bits of the displacement from TP to the target. */
982 HOWTO (R_ALPHA_TPRELHI, /* type */
983 0, /* rightshift */
984 1, /* size (0 = byte, 1 = short, 2 = long) */
985 16, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030986 false, /* pc_relative */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000987 0, /* bitpos */
988 complain_overflow_signed, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +0000989 bfd_elf_generic_reloc, /* special_function */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000990 "TPRELHI", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030991 false, /* partial_inplace */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000992 0xffff, /* src_mask */
993 0xffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +1030994 false), /* pcrel_offset */
Richard Henderson3765b1b2002-05-30 22:01:38 +0000995
996 /* The low 16 bits of the displacement from TP to the target. */
997 HOWTO (R_ALPHA_TPRELLO, /* type */
998 0, /* rightshift */
999 1, /* size (0 = byte, 1 = short, 2 = long) */
1000 16, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +10301001 false, /* pc_relative */
Richard Henderson3765b1b2002-05-30 22:01:38 +00001002 0, /* bitpos */
1003 complain_overflow_dont, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +00001004 bfd_elf_generic_reloc, /* special_function */
Richard Henderson3765b1b2002-05-30 22:01:38 +00001005 "TPRELLO", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +10301006 false, /* partial_inplace */
Richard Henderson3765b1b2002-05-30 22:01:38 +00001007 0xffff, /* src_mask */
1008 0xffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +10301009 false), /* pcrel_offset */
Richard Henderson3765b1b2002-05-30 22:01:38 +00001010
1011 /* A 16-bit displacement from TP to the target. */
1012 HOWTO (R_ALPHA_TPREL16, /* type */
1013 0, /* rightshift */
1014 1, /* size (0 = byte, 1 = short, 2 = long) */
1015 16, /* bitsize */
Alan Modra0a1b45a2021-03-31 10:30:54 +10301016 false, /* pc_relative */
Richard Henderson3765b1b2002-05-30 22:01:38 +00001017 0, /* bitpos */
1018 complain_overflow_signed, /* complain_on_overflow */
Richard Hendersonbc1bc432010-09-20 16:09:03 +00001019 bfd_elf_generic_reloc, /* special_function */
Richard Henderson3765b1b2002-05-30 22:01:38 +00001020 "TPREL16", /* name */
Alan Modra0a1b45a2021-03-31 10:30:54 +10301021 false, /* partial_inplace */
Richard Henderson3765b1b2002-05-30 22:01:38 +00001022 0xffff, /* src_mask */
1023 0xffff, /* dst_mask */
Alan Modra0a1b45a2021-03-31 10:30:54 +10301024 false), /* pcrel_offset */
Richard Henderson252b5131999-05-03 07:29:11 +00001025};
1026
Richard Henderson252b5131999-05-03 07:29:11 +00001027/* A mapping from BFD reloc types to Alpha ELF reloc types. */
1028
1029struct elf_reloc_map
1030{
1031 bfd_reloc_code_real_type bfd_reloc_val;
1032 int elf_reloc_val;
1033};
1034
1035static const struct elf_reloc_map elf64_alpha_reloc_map[] =
1036{
Richard Hendersondfe57ca2001-09-05 03:00:14 +00001037 {BFD_RELOC_NONE, R_ALPHA_NONE},
1038 {BFD_RELOC_32, R_ALPHA_REFLONG},
1039 {BFD_RELOC_64, R_ALPHA_REFQUAD},
1040 {BFD_RELOC_CTOR, R_ALPHA_REFQUAD},
1041 {BFD_RELOC_GPREL32, R_ALPHA_GPREL32},
1042 {BFD_RELOC_ALPHA_ELF_LITERAL, R_ALPHA_LITERAL},
1043 {BFD_RELOC_ALPHA_LITUSE, R_ALPHA_LITUSE},
1044 {BFD_RELOC_ALPHA_GPDISP, R_ALPHA_GPDISP},
1045 {BFD_RELOC_23_PCREL_S2, R_ALPHA_BRADDR},
1046 {BFD_RELOC_ALPHA_HINT, R_ALPHA_HINT},
1047 {BFD_RELOC_16_PCREL, R_ALPHA_SREL16},
1048 {BFD_RELOC_32_PCREL, R_ALPHA_SREL32},
1049 {BFD_RELOC_64_PCREL, R_ALPHA_SREL64},
1050 {BFD_RELOC_ALPHA_GPREL_HI16, R_ALPHA_GPRELHIGH},
1051 {BFD_RELOC_ALPHA_GPREL_LO16, R_ALPHA_GPRELLOW},
1052 {BFD_RELOC_GPREL16, R_ALPHA_GPREL16},
Richard Henderson7793f4d2002-02-09 22:53:53 +00001053 {BFD_RELOC_ALPHA_BRSGP, R_ALPHA_BRSGP},
Richard Henderson3765b1b2002-05-30 22:01:38 +00001054 {BFD_RELOC_ALPHA_TLSGD, R_ALPHA_TLSGD},
1055 {BFD_RELOC_ALPHA_TLSLDM, R_ALPHA_TLSLDM},
1056 {BFD_RELOC_ALPHA_DTPMOD64, R_ALPHA_DTPMOD64},
1057 {BFD_RELOC_ALPHA_GOTDTPREL16, R_ALPHA_GOTDTPREL},
1058 {BFD_RELOC_ALPHA_DTPREL64, R_ALPHA_DTPREL64},
1059 {BFD_RELOC_ALPHA_DTPREL_HI16, R_ALPHA_DTPRELHI},
1060 {BFD_RELOC_ALPHA_DTPREL_LO16, R_ALPHA_DTPRELLO},
1061 {BFD_RELOC_ALPHA_DTPREL16, R_ALPHA_DTPREL16},
1062 {BFD_RELOC_ALPHA_GOTTPREL16, R_ALPHA_GOTTPREL},
1063 {BFD_RELOC_ALPHA_TPREL64, R_ALPHA_TPREL64},
1064 {BFD_RELOC_ALPHA_TPREL_HI16, R_ALPHA_TPRELHI},
1065 {BFD_RELOC_ALPHA_TPREL_LO16, R_ALPHA_TPRELLO},
1066 {BFD_RELOC_ALPHA_TPREL16, R_ALPHA_TPREL16},
Richard Henderson252b5131999-05-03 07:29:11 +00001067};
1068
1069/* Given a BFD reloc type, return a HOWTO structure. */
1070
1071static reloc_howto_type *
Richard Hendersona7519a32005-05-26 07:14:03 +00001072elf64_alpha_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
1073 bfd_reloc_code_real_type code)
Richard Henderson252b5131999-05-03 07:29:11 +00001074{
1075 const struct elf_reloc_map *i, *e;
1076 i = e = elf64_alpha_reloc_map;
1077 e += sizeof (elf64_alpha_reloc_map) / sizeof (struct elf_reloc_map);
1078 for (; i != e; ++i)
1079 {
1080 if (i->bfd_reloc_val == code)
1081 return &elf64_alpha_howto_table[i->elf_reloc_val];
1082 }
1083 return 0;
1084}
1085
Alan Modra157090f2007-03-26 12:23:03 +00001086static reloc_howto_type *
1087elf64_alpha_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
1088 const char *r_name)
1089{
1090 unsigned int i;
1091
1092 for (i = 0;
1093 i < (sizeof (elf64_alpha_howto_table)
1094 / sizeof (elf64_alpha_howto_table[0]));
1095 i++)
1096 if (elf64_alpha_howto_table[i].name != NULL
1097 && strcasecmp (elf64_alpha_howto_table[i].name, r_name) == 0)
1098 return &elf64_alpha_howto_table[i];
1099
1100 return NULL;
1101}
1102
Richard Henderson252b5131999-05-03 07:29:11 +00001103/* Given an Alpha ELF reloc type, fill in an arelent structure. */
1104
Alan Modra0a1b45a2021-03-31 10:30:54 +10301105static bool
Alan Modra0aa13fe2018-02-21 21:47:07 +10301106elf64_alpha_info_to_howto (bfd *abfd, arelent *cache_ptr,
Richard Hendersona7519a32005-05-26 07:14:03 +00001107 Elf_Internal_Rela *dst)
Richard Henderson252b5131999-05-03 07:29:11 +00001108{
Richard Hendersona7519a32005-05-26 07:14:03 +00001109 unsigned r_type = ELF64_R_TYPE(dst->r_info);
Nick Cliftoncd21f5d2015-01-15 16:22:55 +00001110
1111 if (r_type >= R_ALPHA_max)
1112 {
Nick Clifton695344c2016-10-19 14:04:34 +01001113 /* xgettext:c-format */
Alan Modra0aa13fe2018-02-21 21:47:07 +10301114 _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
Alan Modra4eca0222016-09-30 13:00:18 +09301115 abfd, r_type);
Nick Cliftoncd21f5d2015-01-15 16:22:55 +00001116 bfd_set_error (bfd_error_bad_value);
Alan Modra0a1b45a2021-03-31 10:30:54 +10301117 return false;
Nick Cliftoncd21f5d2015-01-15 16:22:55 +00001118 }
Richard Henderson252b5131999-05-03 07:29:11 +00001119 cache_ptr->howto = &elf64_alpha_howto_table[r_type];
Alan Modra0a1b45a2021-03-31 10:30:54 +10301120 return true;
Richard Henderson252b5131999-05-03 07:29:11 +00001121}
Richard Henderson3765b1b2002-05-30 22:01:38 +00001122
1123/* These two relocations create a two-word entry in the got. */
1124#define alpha_got_entry_size(r_type) \
1125 (r_type == R_ALPHA_TLSGD || r_type == R_ALPHA_TLSLDM ? 16 : 8)
Richard Henderson9e756d62002-06-02 02:28:45 +00001126
1127/* This is PT_TLS segment p_vaddr. */
Alan Modrae1918d22003-11-04 06:16:39 +00001128#define alpha_get_dtprel_base(info) \
1129 (elf_hash_table (info)->tls_sec->vma)
Richard Henderson9e756d62002-06-02 02:28:45 +00001130
1131/* Main program TLS (whose template starts at PT_TLS p_vaddr)
1132 is assigned offset round(16, PT_TLS p_align). */
Alan Modrae1918d22003-11-04 06:16:39 +00001133#define alpha_get_tprel_base(info) \
1134 (elf_hash_table (info)->tls_sec->vma \
1135 - align_power ((bfd_vma) 16, \
1136 elf_hash_table (info)->tls_sec->alignment_power))
Richard Henderson252b5131999-05-03 07:29:11 +00001137
Richard Hendersona7519a32005-05-26 07:14:03 +00001138/* Handle an Alpha specific section when reading an object file. This
1139 is called when bfd_section_from_shdr finds a section with an unknown
Alan Modrabf577462020-03-02 10:16:39 +10301140 type. */
Richard Hendersona7519a32005-05-26 07:14:03 +00001141
Alan Modra0a1b45a2021-03-31 10:30:54 +10301142static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00001143elf64_alpha_section_from_shdr (bfd *abfd,
1144 Elf_Internal_Shdr *hdr,
1145 const char *name,
1146 int shindex)
1147{
1148 asection *newsect;
1149
1150 /* There ought to be a place to keep ELF backend specific flags, but
1151 at the moment there isn't one. We just keep track of the
1152 sections by their name, instead. Fortunately, the ABI gives
1153 suggested names for all the MIPS specific sections, so we will
1154 probably get away with this. */
1155 switch (hdr->sh_type)
1156 {
1157 case SHT_ALPHA_DEBUG:
1158 if (strcmp (name, ".mdebug") != 0)
Alan Modra0a1b45a2021-03-31 10:30:54 +10301159 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001160 break;
1161 default:
Alan Modra0a1b45a2021-03-31 10:30:54 +10301162 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001163 }
1164
1165 if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
Alan Modra0a1b45a2021-03-31 10:30:54 +10301166 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001167 newsect = hdr->bfd_section;
1168
1169 if (hdr->sh_type == SHT_ALPHA_DEBUG)
1170 {
Alan Modrafd361982019-09-16 20:25:17 +09301171 if (!bfd_set_section_flags (newsect,
1172 bfd_section_flags (newsect) | SEC_DEBUGGING))
Alan Modra0a1b45a2021-03-31 10:30:54 +10301173 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001174 }
1175
Alan Modra0a1b45a2021-03-31 10:30:54 +10301176 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00001177}
1178
1179/* Convert Alpha specific section flags to bfd internal section flags. */
1180
Alan Modra0a1b45a2021-03-31 10:30:54 +10301181static bool
Alan Modra8c803a22020-03-02 10:16:02 +10301182elf64_alpha_section_flags (const Elf_Internal_Shdr *hdr)
Richard Hendersona7519a32005-05-26 07:14:03 +00001183{
1184 if (hdr->sh_flags & SHF_ALPHA_GPREL)
Alan Modra8c803a22020-03-02 10:16:02 +10301185 hdr->bfd_section->flags |= SEC_SMALL_DATA;
Richard Hendersona7519a32005-05-26 07:14:03 +00001186
Alan Modra0a1b45a2021-03-31 10:30:54 +10301187 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00001188}
1189
1190/* Set the correct type for an Alpha ELF section. We do this by the
1191 section name, which is a hack, but ought to work. */
1192
Alan Modra0a1b45a2021-03-31 10:30:54 +10301193static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00001194elf64_alpha_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec)
1195{
1196 register const char *name;
1197
Alan Modrafd361982019-09-16 20:25:17 +09301198 name = bfd_section_name (sec);
Richard Hendersona7519a32005-05-26 07:14:03 +00001199
1200 if (strcmp (name, ".mdebug") == 0)
1201 {
1202 hdr->sh_type = SHT_ALPHA_DEBUG;
1203 /* In a shared object on Irix 5.3, the .mdebug section has an
Alan Modra07d6d2b2017-12-06 09:26:00 +10301204 entsize of 0. FIXME: Does this matter? */
Richard Hendersona7519a32005-05-26 07:14:03 +00001205 if ((abfd->flags & DYNAMIC) != 0 )
1206 hdr->sh_entsize = 0;
1207 else
1208 hdr->sh_entsize = 1;
1209 }
1210 else if ((sec->flags & SEC_SMALL_DATA)
1211 || strcmp (name, ".sdata") == 0
1212 || strcmp (name, ".sbss") == 0
1213 || strcmp (name, ".lit4") == 0
1214 || strcmp (name, ".lit8") == 0)
1215 hdr->sh_flags |= SHF_ALPHA_GPREL;
1216
Alan Modra0a1b45a2021-03-31 10:30:54 +10301217 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00001218}
1219
1220/* Hook called by the linker routine which adds symbols from an object
1221 file. We use it to put .comm items in .sbss, and not .bss. */
1222
Alan Modra0a1b45a2021-03-31 10:30:54 +10301223static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00001224elf64_alpha_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
1225 Elf_Internal_Sym *sym,
1226 const char **namep ATTRIBUTE_UNUSED,
1227 flagword *flagsp ATTRIBUTE_UNUSED,
1228 asection **secp, bfd_vma *valp)
1229{
1230 if (sym->st_shndx == SHN_COMMON
H.J. Lu0e1862b2015-08-18 05:51:03 -07001231 && !bfd_link_relocatable (info)
Richard Hendersona7519a32005-05-26 07:14:03 +00001232 && sym->st_size <= elf_gp_size (abfd))
1233 {
1234 /* Common symbols less than or equal to -G nn bytes are
1235 automatically put into .sbss. */
1236
1237 asection *scomm = bfd_get_section_by_name (abfd, ".scommon");
1238
1239 if (scomm == NULL)
1240 {
1241 scomm = bfd_make_section_with_flags (abfd, ".scommon",
1242 (SEC_ALLOC
1243 | SEC_IS_COMMON
Alan Modra10885e22020-08-15 14:04:43 +09301244 | SEC_SMALL_DATA
Richard Hendersona7519a32005-05-26 07:14:03 +00001245 | SEC_LINKER_CREATED));
1246 if (scomm == NULL)
Alan Modra0a1b45a2021-03-31 10:30:54 +10301247 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001248 }
1249
1250 *secp = scomm;
1251 *valp = sym->st_size;
1252 }
1253
Alan Modra0a1b45a2021-03-31 10:30:54 +10301254 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00001255}
1256
1257/* Create the .got section. */
1258
Alan Modra0a1b45a2021-03-31 10:30:54 +10301259static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00001260elf64_alpha_create_got_section (bfd *abfd,
1261 struct bfd_link_info *info ATTRIBUTE_UNUSED)
1262{
Alan Modra85d162e2005-07-01 04:46:08 +00001263 flagword flags;
Richard Hendersona7519a32005-05-26 07:14:03 +00001264 asection *s;
1265
Nick Clifton0ffa91d2008-02-12 11:32:31 +00001266 if (! is_alpha_elf (abfd))
Alan Modra0a1b45a2021-03-31 10:30:54 +10301267 return false;
Nick Clifton0ffa91d2008-02-12 11:32:31 +00001268
Alan Modra85d162e2005-07-01 04:46:08 +00001269 flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
1270 | SEC_LINKER_CREATED);
1271 s = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
Richard Hendersona7519a32005-05-26 07:14:03 +00001272 if (s == NULL
Alan Modrafd361982019-09-16 20:25:17 +09301273 || !bfd_set_section_alignment (s, 3))
Alan Modra0a1b45a2021-03-31 10:30:54 +10301274 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001275
1276 alpha_elf_tdata (abfd)->got = s;
1277
Alan Modra85d162e2005-07-01 04:46:08 +00001278 /* Make sure the object's gotobj is set to itself so that we default
1279 to every object with its own .got. We'll merge .gots later once
1280 we've collected each object's info. */
1281 alpha_elf_tdata (abfd)->gotobj = abfd;
1282
Alan Modra0a1b45a2021-03-31 10:30:54 +10301283 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00001284}
1285
1286/* Create all the dynamic sections. */
1287
Alan Modra0a1b45a2021-03-31 10:30:54 +10301288static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00001289elf64_alpha_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
1290{
1291 asection *s;
Alan Modra85d162e2005-07-01 04:46:08 +00001292 flagword flags;
Richard Hendersona7519a32005-05-26 07:14:03 +00001293 struct elf_link_hash_entry *h;
Richard Hendersona7519a32005-05-26 07:14:03 +00001294
Nick Clifton0ffa91d2008-02-12 11:32:31 +00001295 if (! is_alpha_elf (abfd))
Alan Modra0a1b45a2021-03-31 10:30:54 +10301296 return false;
Nick Clifton0ffa91d2008-02-12 11:32:31 +00001297
Richard Hendersona7519a32005-05-26 07:14:03 +00001298 /* We need to create .plt, .rela.plt, .got, and .rela.got sections. */
1299
Alan Modra85d162e2005-07-01 04:46:08 +00001300 flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_IN_MEMORY
1301 | SEC_LINKER_CREATED
1302 | (elf64_alpha_use_secureplt ? SEC_READONLY : 0));
1303 s = bfd_make_section_anyway_with_flags (abfd, ".plt", flags);
Alan Modrace558b82016-11-23 15:06:34 +10301304 elf_hash_table (info)->splt = s;
Alan Modrafd361982019-09-16 20:25:17 +09301305 if (s == NULL || ! bfd_set_section_alignment (s, 4))
Alan Modra0a1b45a2021-03-31 10:30:54 +10301306 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001307
1308 /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
1309 .plt section. */
Richard Sandiford73253062006-02-25 09:23:30 +00001310 h = _bfd_elf_define_linkage_sym (abfd, info, s,
1311 "_PROCEDURE_LINKAGE_TABLE_");
1312 elf_hash_table (info)->hplt = h;
1313 if (h == NULL)
Alan Modra0a1b45a2021-03-31 10:30:54 +10301314 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001315
Alan Modra85d162e2005-07-01 04:46:08 +00001316 flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
1317 | SEC_LINKER_CREATED | SEC_READONLY);
1318 s = bfd_make_section_anyway_with_flags (abfd, ".rela.plt", flags);
Alan Modrace558b82016-11-23 15:06:34 +10301319 elf_hash_table (info)->srelplt = s;
Alan Modrafd361982019-09-16 20:25:17 +09301320 if (s == NULL || ! bfd_set_section_alignment (s, 3))
Alan Modra0a1b45a2021-03-31 10:30:54 +10301321 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001322
Richard Henderson6ec70572005-05-29 23:13:39 +00001323 if (elf64_alpha_use_secureplt)
1324 {
Alan Modra85d162e2005-07-01 04:46:08 +00001325 flags = SEC_ALLOC | SEC_LINKER_CREATED;
1326 s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
Alan Modrace558b82016-11-23 15:06:34 +10301327 elf_hash_table (info)->sgotplt = s;
Alan Modrafd361982019-09-16 20:25:17 +09301328 if (s == NULL || ! bfd_set_section_alignment (s, 3))
Alan Modra0a1b45a2021-03-31 10:30:54 +10301329 return false;
Richard Henderson6ec70572005-05-29 23:13:39 +00001330 }
1331
Richard Hendersona7519a32005-05-26 07:14:03 +00001332 /* We may or may not have created a .got section for this object, but
1333 we definitely havn't done the rest of the work. */
1334
Alan Modra85d162e2005-07-01 04:46:08 +00001335 if (alpha_elf_tdata(abfd)->gotobj == NULL)
1336 {
1337 if (!elf64_alpha_create_got_section (abfd, info))
Alan Modra0a1b45a2021-03-31 10:30:54 +10301338 return false;
Alan Modra85d162e2005-07-01 04:46:08 +00001339 }
Richard Hendersona7519a32005-05-26 07:14:03 +00001340
Alan Modra85d162e2005-07-01 04:46:08 +00001341 flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
1342 | SEC_LINKER_CREATED | SEC_READONLY);
1343 s = bfd_make_section_anyway_with_flags (abfd, ".rela.got", flags);
Alan Modrace558b82016-11-23 15:06:34 +10301344 elf_hash_table (info)->srelgot = s;
Richard Hendersona7519a32005-05-26 07:14:03 +00001345 if (s == NULL
Alan Modrafd361982019-09-16 20:25:17 +09301346 || !bfd_set_section_alignment (s, 3))
Alan Modra0a1b45a2021-03-31 10:30:54 +10301347 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001348
1349 /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the
1350 dynobj's .got section. We don't do this in the linker script
1351 because we don't want to define the symbol if we are not creating
1352 a global offset table. */
Alan Modrad98685a2005-08-15 15:39:08 +00001353 h = _bfd_elf_define_linkage_sym (abfd, info, alpha_elf_tdata(abfd)->got,
1354 "_GLOBAL_OFFSET_TABLE_");
Richard Hendersona7519a32005-05-26 07:14:03 +00001355 elf_hash_table (info)->hgot = h;
Alan Modrad98685a2005-08-15 15:39:08 +00001356 if (h == NULL)
Alan Modra0a1b45a2021-03-31 10:30:54 +10301357 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001358
Alan Modra0a1b45a2021-03-31 10:30:54 +10301359 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00001360}
1361
1362/* Read ECOFF debugging information from a .mdebug section into a
1363 ecoff_debug_info structure. */
1364
Alan Modra0a1b45a2021-03-31 10:30:54 +10301365static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00001366elf64_alpha_read_ecoff_info (bfd *abfd, asection *section,
1367 struct ecoff_debug_info *debug)
1368{
1369 HDRR *symhdr;
1370 const struct ecoff_debug_swap *swap;
1371 char *ext_hdr = NULL;
1372
1373 swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
1374 memset (debug, 0, sizeof (*debug));
1375
1376 ext_hdr = (char *) bfd_malloc (swap->external_hdr_size);
1377 if (ext_hdr == NULL && swap->external_hdr_size != 0)
1378 goto error_return;
1379
1380 if (! bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0,
1381 swap->external_hdr_size))
1382 goto error_return;
1383
1384 symhdr = &debug->symbolic_header;
1385 (*swap->swap_hdr_in) (abfd, ext_hdr, symhdr);
1386
1387 /* The symbolic header contains absolute file offsets and sizes to
1388 read. */
1389#define READ(ptr, offset, count, size, type) \
Alan Modra1f4361a2020-02-19 13:15:06 +10301390 do \
Richard Hendersona7519a32005-05-26 07:14:03 +00001391 { \
Alan Modra1f4361a2020-02-19 13:15:06 +10301392 size_t amt; \
1393 debug->ptr = NULL; \
1394 if (symhdr->count == 0) \
1395 break; \
1396 if (_bfd_mul_overflow (size, symhdr->count, &amt)) \
1397 { \
1398 bfd_set_error (bfd_error_file_too_big); \
1399 goto error_return; \
1400 } \
Alan Modra2bb36872020-02-19 13:16:01 +10301401 if (bfd_seek (abfd, symhdr->offset, SEEK_SET) != 0) \
Richard Hendersona7519a32005-05-26 07:14:03 +00001402 goto error_return; \
Alan Modra2bb36872020-02-19 13:16:01 +10301403 debug->ptr = (type) _bfd_malloc_and_read (abfd, amt, amt); \
1404 if (debug->ptr == NULL) \
Richard Hendersona7519a32005-05-26 07:14:03 +00001405 goto error_return; \
Alan Modra1f4361a2020-02-19 13:15:06 +10301406 } while (0)
Richard Hendersona7519a32005-05-26 07:14:03 +00001407
1408 READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *);
Nick Clifton2c3fc382012-07-13 14:22:50 +00001409 READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *);
1410 READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, void *);
1411 READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, void *);
1412 READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, void *);
Richard Hendersona7519a32005-05-26 07:14:03 +00001413 READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
1414 union aux_ext *);
1415 READ (ss, cbSsOffset, issMax, sizeof (char), char *);
1416 READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *);
Nick Clifton2c3fc382012-07-13 14:22:50 +00001417 READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, void *);
1418 READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, void *);
1419 READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, void *);
Richard Hendersona7519a32005-05-26 07:14:03 +00001420#undef READ
1421
1422 debug->fdr = NULL;
1423
Alan Modra0a1b45a2021-03-31 10:30:54 +10301424 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00001425
1426 error_return:
Alan Modrac9594982020-05-20 17:25:20 +09301427 free (ext_hdr);
1428 free (debug->line);
1429 free (debug->external_dnr);
1430 free (debug->external_pdr);
1431 free (debug->external_sym);
1432 free (debug->external_opt);
1433 free (debug->external_aux);
1434 free (debug->ss);
1435 free (debug->ssext);
1436 free (debug->external_fdr);
1437 free (debug->external_rfd);
1438 free (debug->external_ext);
Alan Modra0a1b45a2021-03-31 10:30:54 +10301439 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001440}
1441
1442/* Alpha ELF local labels start with '$'. */
1443
Alan Modra0a1b45a2021-03-31 10:30:54 +10301444static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00001445elf64_alpha_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, const char *name)
1446{
1447 return name[0] == '$';
1448}
1449
Alan Modra0a1b45a2021-03-31 10:30:54 +10301450static bool
Alan Modrafb167eb2014-10-15 21:52:20 +10301451elf64_alpha_find_nearest_line (bfd *abfd, asymbol **symbols,
1452 asection *section, bfd_vma offset,
1453 const char **filename_ptr,
Richard Hendersona7519a32005-05-26 07:14:03 +00001454 const char **functionname_ptr,
Alan Modrafb167eb2014-10-15 21:52:20 +10301455 unsigned int *line_ptr,
1456 unsigned int *discriminator_ptr)
Richard Hendersona7519a32005-05-26 07:14:03 +00001457{
1458 asection *msec;
1459
Alan Modrafb167eb2014-10-15 21:52:20 +10301460 if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
Richard Hendersona7519a32005-05-26 07:14:03 +00001461 filename_ptr, functionname_ptr,
Alan Modrafb167eb2014-10-15 21:52:20 +10301462 line_ptr, discriminator_ptr,
Alan Modra9defd222019-08-14 10:40:20 +09301463 dwarf_debug_sections,
Alan Modra7f3bf382019-11-27 18:00:59 +10301464 &elf_tdata (abfd)->dwarf2_find_line_info)
1465 == 1)
Alan Modra0a1b45a2021-03-31 10:30:54 +10301466 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00001467
1468 msec = bfd_get_section_by_name (abfd, ".mdebug");
1469 if (msec != NULL)
1470 {
1471 flagword origflags;
Alan Modra698600e2013-02-18 02:56:58 +00001472 struct alpha_elf_find_line *fi;
Richard Hendersona7519a32005-05-26 07:14:03 +00001473 const struct ecoff_debug_swap * const swap =
1474 get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
1475
1476 /* If we are called during a link, alpha_elf_final_link may have
1477 cleared the SEC_HAS_CONTENTS field. We force it back on here
1478 if appropriate (which it normally will be). */
1479 origflags = msec->flags;
1480 if (elf_section_data (msec)->this_hdr.sh_type != SHT_NOBITS)
1481 msec->flags |= SEC_HAS_CONTENTS;
1482
Alan Modra698600e2013-02-18 02:56:58 +00001483 fi = alpha_elf_tdata (abfd)->find_line_info;
Richard Hendersona7519a32005-05-26 07:14:03 +00001484 if (fi == NULL)
1485 {
1486 bfd_size_type external_fdr_size;
1487 char *fraw_src;
1488 char *fraw_end;
1489 struct fdr *fdr_ptr;
Alan Modra698600e2013-02-18 02:56:58 +00001490 bfd_size_type amt = sizeof (struct alpha_elf_find_line);
Richard Hendersona7519a32005-05-26 07:14:03 +00001491
Alan Modra698600e2013-02-18 02:56:58 +00001492 fi = (struct alpha_elf_find_line *) bfd_zalloc (abfd, amt);
Richard Hendersona7519a32005-05-26 07:14:03 +00001493 if (fi == NULL)
1494 {
1495 msec->flags = origflags;
Alan Modra0a1b45a2021-03-31 10:30:54 +10301496 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001497 }
1498
1499 if (!elf64_alpha_read_ecoff_info (abfd, msec, &fi->d))
1500 {
1501 msec->flags = origflags;
Alan Modra0a1b45a2021-03-31 10:30:54 +10301502 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001503 }
1504
1505 /* Swap in the FDR information. */
1506 amt = fi->d.symbolic_header.ifdMax * sizeof (struct fdr);
1507 fi->d.fdr = (struct fdr *) bfd_alloc (abfd, amt);
1508 if (fi->d.fdr == NULL)
1509 {
1510 msec->flags = origflags;
Alan Modra0a1b45a2021-03-31 10:30:54 +10301511 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001512 }
1513 external_fdr_size = swap->external_fdr_size;
1514 fdr_ptr = fi->d.fdr;
1515 fraw_src = (char *) fi->d.external_fdr;
1516 fraw_end = (fraw_src
1517 + fi->d.symbolic_header.ifdMax * external_fdr_size);
1518 for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
Nick Clifton2c3fc382012-07-13 14:22:50 +00001519 (*swap->swap_fdr_in) (abfd, fraw_src, fdr_ptr);
Richard Hendersona7519a32005-05-26 07:14:03 +00001520
Alan Modra698600e2013-02-18 02:56:58 +00001521 alpha_elf_tdata (abfd)->find_line_info = fi;
Richard Hendersona7519a32005-05-26 07:14:03 +00001522
1523 /* Note that we don't bother to ever free this information.
Alan Modra07d6d2b2017-12-06 09:26:00 +10301524 find_nearest_line is either called all the time, as in
1525 objdump -l, so the information should be saved, or it is
1526 rarely called, as in ld error messages, so the memory
1527 wasted is unimportant. Still, it would probably be a
1528 good idea for free_cached_info to throw it away. */
Richard Hendersona7519a32005-05-26 07:14:03 +00001529 }
1530
1531 if (_bfd_ecoff_locate_line (abfd, section, offset, &fi->d, swap,
1532 &fi->i, filename_ptr, functionname_ptr,
1533 line_ptr))
1534 {
1535 msec->flags = origflags;
Alan Modra0a1b45a2021-03-31 10:30:54 +10301536 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00001537 }
1538
1539 msec->flags = origflags;
1540 }
1541
1542 /* Fall back on the generic ELF find_nearest_line routine. */
1543
Alan Modrafb167eb2014-10-15 21:52:20 +10301544 return _bfd_elf_find_nearest_line (abfd, symbols, section, offset,
Richard Hendersona7519a32005-05-26 07:14:03 +00001545 filename_ptr, functionname_ptr,
Alan Modrafb167eb2014-10-15 21:52:20 +10301546 line_ptr, discriminator_ptr);
Richard Hendersona7519a32005-05-26 07:14:03 +00001547}
1548
1549/* Structure used to pass information to alpha_elf_output_extsym. */
1550
1551struct extsym_info
1552{
1553 bfd *abfd;
1554 struct bfd_link_info *info;
1555 struct ecoff_debug_info *debug;
1556 const struct ecoff_debug_swap *swap;
Alan Modra0a1b45a2021-03-31 10:30:54 +10301557 bool failed;
Richard Hendersona7519a32005-05-26 07:14:03 +00001558};
1559
Alan Modra0a1b45a2021-03-31 10:30:54 +10301560static bool
Alan Modra2cc15b12021-04-12 17:16:03 +09301561elf64_alpha_output_extsym (struct elf_link_hash_entry *x, void * data)
Richard Hendersona7519a32005-05-26 07:14:03 +00001562{
Alan Modra2cc15b12021-04-12 17:16:03 +09301563 struct alpha_elf_link_hash_entry *h = (struct alpha_elf_link_hash_entry *) x;
Richard Hendersona7519a32005-05-26 07:14:03 +00001564 struct extsym_info *einfo = (struct extsym_info *) data;
Alan Modra0a1b45a2021-03-31 10:30:54 +10301565 bool strip;
Richard Hendersona7519a32005-05-26 07:14:03 +00001566 asection *sec, *output_section;
1567
Richard Hendersona7519a32005-05-26 07:14:03 +00001568 if (h->root.indx == -2)
Alan Modra0a1b45a2021-03-31 10:30:54 +10301569 strip = false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001570 else if ((h->root.def_dynamic
1571 || h->root.ref_dynamic
1572 || h->root.root.type == bfd_link_hash_new)
1573 && !h->root.def_regular
1574 && !h->root.ref_regular)
Alan Modra0a1b45a2021-03-31 10:30:54 +10301575 strip = true;
Richard Hendersona7519a32005-05-26 07:14:03 +00001576 else if (einfo->info->strip == strip_all
1577 || (einfo->info->strip == strip_some
1578 && bfd_hash_lookup (einfo->info->keep_hash,
1579 h->root.root.root.string,
Alan Modra0a1b45a2021-03-31 10:30:54 +10301580 false, false) == NULL))
1581 strip = true;
Richard Hendersona7519a32005-05-26 07:14:03 +00001582 else
Alan Modra0a1b45a2021-03-31 10:30:54 +10301583 strip = false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001584
1585 if (strip)
Alan Modra0a1b45a2021-03-31 10:30:54 +10301586 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00001587
1588 if (h->esym.ifd == -2)
1589 {
1590 h->esym.jmptbl = 0;
1591 h->esym.cobol_main = 0;
1592 h->esym.weakext = 0;
1593 h->esym.reserved = 0;
1594 h->esym.ifd = ifdNil;
1595 h->esym.asym.value = 0;
1596 h->esym.asym.st = stGlobal;
1597
1598 if (h->root.root.type != bfd_link_hash_defined
1599 && h->root.root.type != bfd_link_hash_defweak)
1600 h->esym.asym.sc = scAbs;
1601 else
1602 {
1603 const char *name;
1604
1605 sec = h->root.root.u.def.section;
1606 output_section = sec->output_section;
1607
1608 /* When making a shared library and symbol h is the one from
1609 the another shared library, OUTPUT_SECTION may be null. */
1610 if (output_section == NULL)
1611 h->esym.asym.sc = scUndefined;
1612 else
1613 {
Alan Modrafd361982019-09-16 20:25:17 +09301614 name = bfd_section_name (output_section);
Richard Hendersona7519a32005-05-26 07:14:03 +00001615
1616 if (strcmp (name, ".text") == 0)
1617 h->esym.asym.sc = scText;
1618 else if (strcmp (name, ".data") == 0)
1619 h->esym.asym.sc = scData;
1620 else if (strcmp (name, ".sdata") == 0)
1621 h->esym.asym.sc = scSData;
1622 else if (strcmp (name, ".rodata") == 0
1623 || strcmp (name, ".rdata") == 0)
1624 h->esym.asym.sc = scRData;
1625 else if (strcmp (name, ".bss") == 0)
1626 h->esym.asym.sc = scBss;
1627 else if (strcmp (name, ".sbss") == 0)
1628 h->esym.asym.sc = scSBss;
1629 else if (strcmp (name, ".init") == 0)
1630 h->esym.asym.sc = scInit;
1631 else if (strcmp (name, ".fini") == 0)
1632 h->esym.asym.sc = scFini;
1633 else
1634 h->esym.asym.sc = scAbs;
1635 }
1636 }
1637
1638 h->esym.asym.reserved = 0;
1639 h->esym.asym.index = indexNil;
1640 }
1641
1642 if (h->root.root.type == bfd_link_hash_common)
1643 h->esym.asym.value = h->root.root.u.c.size;
1644 else if (h->root.root.type == bfd_link_hash_defined
1645 || h->root.root.type == bfd_link_hash_defweak)
1646 {
1647 if (h->esym.asym.sc == scCommon)
1648 h->esym.asym.sc = scBss;
1649 else if (h->esym.asym.sc == scSCommon)
1650 h->esym.asym.sc = scSBss;
1651
1652 sec = h->root.root.u.def.section;
1653 output_section = sec->output_section;
1654 if (output_section != NULL)
1655 h->esym.asym.value = (h->root.root.u.def.value
1656 + sec->output_offset
1657 + output_section->vma);
1658 else
1659 h->esym.asym.value = 0;
1660 }
Richard Hendersona7519a32005-05-26 07:14:03 +00001661
1662 if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap,
1663 h->root.root.root.string,
1664 &h->esym))
1665 {
Alan Modra0a1b45a2021-03-31 10:30:54 +10301666 einfo->failed = true;
1667 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001668 }
1669
Alan Modra0a1b45a2021-03-31 10:30:54 +10301670 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00001671}
1672
1673/* Search for and possibly create a got entry. */
1674
1675static struct alpha_elf_got_entry *
1676get_got_entry (bfd *abfd, struct alpha_elf_link_hash_entry *h,
1677 unsigned long r_type, unsigned long r_symndx,
1678 bfd_vma r_addend)
1679{
1680 struct alpha_elf_got_entry *gotent;
1681 struct alpha_elf_got_entry **slot;
1682
1683 if (h)
1684 slot = &h->got_entries;
1685 else
1686 {
1687 /* This is a local .got entry -- record for merge. */
1688
1689 struct alpha_elf_got_entry **local_got_entries;
1690
1691 local_got_entries = alpha_elf_tdata(abfd)->local_got_entries;
1692 if (!local_got_entries)
1693 {
1694 bfd_size_type size;
1695 Elf_Internal_Shdr *symtab_hdr;
1696
1697 symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
1698 size = symtab_hdr->sh_info;
1699 size *= sizeof (struct alpha_elf_got_entry *);
1700
1701 local_got_entries
1702 = (struct alpha_elf_got_entry **) bfd_zalloc (abfd, size);
1703 if (!local_got_entries)
1704 return NULL;
1705
1706 alpha_elf_tdata (abfd)->local_got_entries = local_got_entries;
1707 }
1708
1709 slot = &local_got_entries[r_symndx];
1710 }
1711
1712 for (gotent = *slot; gotent ; gotent = gotent->next)
1713 if (gotent->gotobj == abfd
1714 && gotent->reloc_type == r_type
1715 && gotent->addend == r_addend)
1716 break;
1717
1718 if (!gotent)
1719 {
1720 int entry_size;
Alan Modra986f0782020-02-19 13:12:00 +10301721 size_t amt;
Richard Hendersona7519a32005-05-26 07:14:03 +00001722
1723 amt = sizeof (struct alpha_elf_got_entry);
1724 gotent = (struct alpha_elf_got_entry *) bfd_alloc (abfd, amt);
1725 if (!gotent)
1726 return NULL;
1727
1728 gotent->gotobj = abfd;
1729 gotent->addend = r_addend;
1730 gotent->got_offset = -1;
Richard Henderson6ec70572005-05-29 23:13:39 +00001731 gotent->plt_offset = -1;
Richard Hendersona7519a32005-05-26 07:14:03 +00001732 gotent->use_count = 1;
1733 gotent->reloc_type = r_type;
1734 gotent->reloc_done = 0;
1735 gotent->reloc_xlated = 0;
1736
1737 gotent->next = *slot;
1738 *slot = gotent;
1739
1740 entry_size = alpha_got_entry_size (r_type);
1741 alpha_elf_tdata (abfd)->total_got_size += entry_size;
1742 if (!h)
1743 alpha_elf_tdata(abfd)->local_got_size += entry_size;
1744 }
1745 else
1746 gotent->use_count += 1;
1747
1748 return gotent;
1749}
1750
Alan Modra0a1b45a2021-03-31 10:30:54 +10301751static bool
Richard Henderson6ec70572005-05-29 23:13:39 +00001752elf64_alpha_want_plt (struct alpha_elf_link_hash_entry *ah)
1753{
1754 return ((ah->root.type == STT_FUNC
1755 || ah->root.root.type == bfd_link_hash_undefweak
1756 || ah->root.root.type == bfd_link_hash_undefined)
Richard Henderson8288a392005-05-31 22:53:44 +00001757 && (ah->flags & ALPHA_ELF_LINK_HASH_LU_PLT) != 0
1758 && (ah->flags & ~ALPHA_ELF_LINK_HASH_LU_PLT) == 0);
Richard Henderson6ec70572005-05-29 23:13:39 +00001759}
1760
Alan Modra6fc5bb52015-08-27 10:54:28 +09301761/* Whether to sort relocs output by ld -r or ld --emit-relocs, by r_offset.
1762 Don't do so for code sections. We want to keep ordering of LITERAL/LITUSE
1763 as is. On the other hand, elf-eh-frame.c processing requires .eh_frame
1764 relocs to be sorted. */
1765
Alan Modra0a1b45a2021-03-31 10:30:54 +10301766static bool
Alan Modra6fc5bb52015-08-27 10:54:28 +09301767elf64_alpha_sort_relocs_p (asection *sec)
1768{
1769 return (sec->flags & SEC_CODE) == 0;
1770}
1771
1772
Richard Hendersona7519a32005-05-26 07:14:03 +00001773/* Handle dynamic relocations when doing an Alpha ELF link. */
1774
Alan Modra0a1b45a2021-03-31 10:30:54 +10301775static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00001776elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
1777 asection *sec, const Elf_Internal_Rela *relocs)
1778{
1779 bfd *dynobj;
1780 asection *sreloc;
Richard Hendersona7519a32005-05-26 07:14:03 +00001781 Elf_Internal_Shdr *symtab_hdr;
1782 struct alpha_elf_link_hash_entry **sym_hashes;
1783 const Elf_Internal_Rela *rel, *relend;
Richard Hendersona7519a32005-05-26 07:14:03 +00001784
H.J. Lu0e1862b2015-08-18 05:51:03 -07001785 if (bfd_link_relocatable (info))
Alan Modra0a1b45a2021-03-31 10:30:54 +10301786 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00001787
Nick Clifton0ffa91d2008-02-12 11:32:31 +00001788 BFD_ASSERT (is_alpha_elf (abfd));
1789
1790 dynobj = elf_hash_table (info)->dynobj;
Richard Hendersona7519a32005-05-26 07:14:03 +00001791 if (dynobj == NULL)
Nick Clifton0ffa91d2008-02-12 11:32:31 +00001792 elf_hash_table (info)->dynobj = dynobj = abfd;
Richard Hendersona7519a32005-05-26 07:14:03 +00001793
1794 sreloc = NULL;
Nick Clifton0ffa91d2008-02-12 11:32:31 +00001795 symtab_hdr = &elf_symtab_hdr (abfd);
1796 sym_hashes = alpha_elf_sym_hashes (abfd);
Richard Hendersona7519a32005-05-26 07:14:03 +00001797
1798 relend = relocs + sec->reloc_count;
1799 for (rel = relocs; rel < relend; ++rel)
1800 {
1801 enum {
1802 NEED_GOT = 1,
1803 NEED_GOT_ENTRY = 2,
1804 NEED_DYNREL = 4
1805 };
1806
1807 unsigned long r_symndx, r_type;
1808 struct alpha_elf_link_hash_entry *h;
1809 unsigned int gotent_flags;
Alan Modra0a1b45a2021-03-31 10:30:54 +10301810 bool maybe_dynamic;
Richard Hendersona7519a32005-05-26 07:14:03 +00001811 unsigned int need;
1812 bfd_vma addend;
1813
1814 r_symndx = ELF64_R_SYM (rel->r_info);
1815 if (r_symndx < symtab_hdr->sh_info)
1816 h = NULL;
1817 else
1818 {
1819 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
1820
1821 while (h->root.root.type == bfd_link_hash_indirect
1822 || h->root.root.type == bfd_link_hash_warning)
1823 h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
1824
Alan Modra81fbe832013-03-30 10:14:15 +00001825 /* PR15323, ref flags aren't set for references in the same
1826 object. */
Richard Hendersona7519a32005-05-26 07:14:03 +00001827 h->root.ref_regular = 1;
1828 }
1829
1830 /* We can only get preliminary data on whether a symbol is
Alan Modra07d6d2b2017-12-06 09:26:00 +10301831 locally or externally defined, as not all of the input files
1832 have yet been processed. Do something with what we know, as
1833 this may help reduce memory usage and processing time later. */
Alan Modra0a1b45a2021-03-31 10:30:54 +10301834 maybe_dynamic = false;
H.J. Lu0e1862b2015-08-18 05:51:03 -07001835 if (h && ((bfd_link_pic (info)
Richard Hendersona7519a32005-05-26 07:14:03 +00001836 && (!info->symbolic
1837 || info->unresolved_syms_in_shared_libs == RM_IGNORE))
1838 || !h->root.def_regular
1839 || h->root.root.type == bfd_link_hash_defweak))
Alan Modra0a1b45a2021-03-31 10:30:54 +10301840 maybe_dynamic = true;
Richard Hendersona7519a32005-05-26 07:14:03 +00001841
1842 need = 0;
1843 gotent_flags = 0;
1844 r_type = ELF64_R_TYPE (rel->r_info);
1845 addend = rel->r_addend;
1846
1847 switch (r_type)
1848 {
1849 case R_ALPHA_LITERAL:
1850 need = NEED_GOT | NEED_GOT_ENTRY;
1851
1852 /* Remember how this literal is used from its LITUSEs.
1853 This will be important when it comes to decide if we can
1854 create a .plt entry for a function symbol. */
1855 while (++rel < relend && ELF64_R_TYPE (rel->r_info) == R_ALPHA_LITUSE)
Richard Henderson8288a392005-05-31 22:53:44 +00001856 if (rel->r_addend >= 1 && rel->r_addend <= 6)
Richard Hendersona7519a32005-05-26 07:14:03 +00001857 gotent_flags |= 1 << rel->r_addend;
1858 --rel;
1859
1860 /* No LITUSEs -- presumably the address is used somehow. */
1861 if (gotent_flags == 0)
1862 gotent_flags = ALPHA_ELF_LINK_HASH_LU_ADDR;
1863 break;
1864
1865 case R_ALPHA_GPDISP:
1866 case R_ALPHA_GPREL16:
1867 case R_ALPHA_GPREL32:
1868 case R_ALPHA_GPRELHIGH:
1869 case R_ALPHA_GPRELLOW:
1870 case R_ALPHA_BRSGP:
1871 need = NEED_GOT;
1872 break;
1873
1874 case R_ALPHA_REFLONG:
1875 case R_ALPHA_REFQUAD:
H.J. Lu0e1862b2015-08-18 05:51:03 -07001876 if (bfd_link_pic (info) || maybe_dynamic)
Richard Hendersona7519a32005-05-26 07:14:03 +00001877 need = NEED_DYNREL;
1878 break;
1879
1880 case R_ALPHA_TLSLDM:
1881 /* The symbol for a TLSLDM reloc is ignored. Collapse the
Thomas Schwingecf356382010-09-24 12:14:26 +00001882 reloc to the STN_UNDEF (0) symbol so that they all match. */
1883 r_symndx = STN_UNDEF;
Richard Hendersona7519a32005-05-26 07:14:03 +00001884 h = 0;
Alan Modra0a1b45a2021-03-31 10:30:54 +10301885 maybe_dynamic = false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001886 /* FALLTHRU */
1887
1888 case R_ALPHA_TLSGD:
1889 case R_ALPHA_GOTDTPREL:
1890 need = NEED_GOT | NEED_GOT_ENTRY;
1891 break;
1892
1893 case R_ALPHA_GOTTPREL:
1894 need = NEED_GOT | NEED_GOT_ENTRY;
1895 gotent_flags = ALPHA_ELF_LINK_HASH_TLS_IE;
H.J. Lu0e1862b2015-08-18 05:51:03 -07001896 if (bfd_link_pic (info))
Richard Hendersona7519a32005-05-26 07:14:03 +00001897 info->flags |= DF_STATIC_TLS;
1898 break;
1899
1900 case R_ALPHA_TPREL64:
Alan Modra3cbc1e52015-08-19 11:57:40 +09301901 if (bfd_link_dll (info))
Richard Hendersone366eea2011-06-22 16:18:24 +00001902 {
1903 info->flags |= DF_STATIC_TLS;
1904 need = NEED_DYNREL;
1905 }
1906 else if (maybe_dynamic)
Richard Hendersona7519a32005-05-26 07:14:03 +00001907 need = NEED_DYNREL;
Richard Hendersona7519a32005-05-26 07:14:03 +00001908 break;
1909 }
1910
1911 if (need & NEED_GOT)
1912 {
Alan Modra85d162e2005-07-01 04:46:08 +00001913 if (alpha_elf_tdata(abfd)->gotobj == NULL)
Richard Hendersona7519a32005-05-26 07:14:03 +00001914 {
1915 if (!elf64_alpha_create_got_section (abfd, info))
Alan Modra0a1b45a2021-03-31 10:30:54 +10301916 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001917 }
1918 }
1919
1920 if (need & NEED_GOT_ENTRY)
1921 {
1922 struct alpha_elf_got_entry *gotent;
1923
1924 gotent = get_got_entry (abfd, h, r_type, r_symndx, addend);
1925 if (!gotent)
Alan Modra0a1b45a2021-03-31 10:30:54 +10301926 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001927
1928 if (gotent_flags)
1929 {
1930 gotent->flags |= gotent_flags;
1931 if (h)
1932 {
1933 gotent_flags |= h->flags;
1934 h->flags = gotent_flags;
1935
1936 /* Make a guess as to whether a .plt entry is needed. */
Richard Henderson6ec70572005-05-29 23:13:39 +00001937 /* ??? It appears that we won't make it into
1938 adjust_dynamic_symbol for symbols that remain
1939 totally undefined. Copying this check here means
1940 we can create a plt entry for them too. */
1941 h->root.needs_plt
1942 = (maybe_dynamic && elf64_alpha_want_plt (h));
1943 }
Richard Hendersona7519a32005-05-26 07:14:03 +00001944 }
1945 }
1946
1947 if (need & NEED_DYNREL)
1948 {
Richard Hendersona7519a32005-05-26 07:14:03 +00001949 /* We need to create the section here now whether we eventually
1950 use it or not so that it gets mapped to an output section by
Nick Clifton83bac4b2008-11-25 13:03:56 +00001951 the linker. If not used, we'll kill it in size_dynamic_sections. */
Richard Hendersona7519a32005-05-26 07:14:03 +00001952 if (sreloc == NULL)
1953 {
Nick Clifton83bac4b2008-11-25 13:03:56 +00001954 sreloc = _bfd_elf_make_dynamic_reloc_section
Alan Modra0a1b45a2021-03-31 10:30:54 +10301955 (sec, dynobj, 3, abfd, /*rela?*/ true);
Richard Hendersona7519a32005-05-26 07:14:03 +00001956
Nick Clifton83bac4b2008-11-25 13:03:56 +00001957 if (sreloc == NULL)
Alan Modra0a1b45a2021-03-31 10:30:54 +10301958 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001959 }
1960
1961 if (h)
1962 {
1963 /* Since we havn't seen all of the input symbols yet, we
1964 don't know whether we'll actually need a dynamic relocation
1965 entry for this reloc. So make a record of it. Once we
1966 find out if this thing needs dynamic relocation we'll
1967 expand the relocation sections by the appropriate amount. */
1968
1969 struct alpha_elf_reloc_entry *rent;
1970
1971 for (rent = h->reloc_entries; rent; rent = rent->next)
1972 if (rent->rtype == r_type && rent->srel == sreloc)
1973 break;
1974
1975 if (!rent)
1976 {
Alan Modra986f0782020-02-19 13:12:00 +10301977 size_t amt = sizeof (struct alpha_elf_reloc_entry);
Richard Hendersona7519a32005-05-26 07:14:03 +00001978 rent = (struct alpha_elf_reloc_entry *) bfd_alloc (abfd, amt);
1979 if (!rent)
Alan Modra0a1b45a2021-03-31 10:30:54 +10301980 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00001981
1982 rent->srel = sreloc;
H.J. Lu1f7f2ab2020-04-21 05:20:11 -07001983 rent->sec = sec;
Richard Hendersona7519a32005-05-26 07:14:03 +00001984 rent->rtype = r_type;
1985 rent->count = 1;
Richard Hendersona7519a32005-05-26 07:14:03 +00001986
1987 rent->next = h->reloc_entries;
1988 h->reloc_entries = rent;
1989 }
1990 else
1991 rent->count++;
1992 }
H.J. Lu0e1862b2015-08-18 05:51:03 -07001993 else if (bfd_link_pic (info))
Richard Hendersona7519a32005-05-26 07:14:03 +00001994 {
1995 /* If this is a shared library, and the section is to be
1996 loaded into memory, we need a RELATIVE reloc. */
1997 sreloc->size += sizeof (Elf64_External_Rela);
1998 if (sec->flags & SEC_READONLY)
H.J. Lu1f7f2ab2020-04-21 05:20:11 -07001999 {
2000 info->flags |= DF_TEXTREL;
2001 info->callbacks->minfo
2002 (_("%pB: dynamic relocation against `%pT' in "
2003 "read-only section `%pA'\n"),
2004 sec->owner, h->root.root.root.string, sec);
2005 }
Richard Hendersona7519a32005-05-26 07:14:03 +00002006 }
2007 }
2008 }
2009
Alan Modra0a1b45a2021-03-31 10:30:54 +10302010 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002011}
2012
Richard Hendersone1173602011-03-29 21:18:16 +00002013/* Return the section that should be marked against GC for a given
2014 relocation. */
2015
2016static asection *
2017elf64_alpha_gc_mark_hook (asection *sec, struct bfd_link_info *info,
2018 Elf_Internal_Rela *rel,
2019 struct elf_link_hash_entry *h, Elf_Internal_Sym *sym)
2020{
2021 /* These relocations don't really reference a symbol. Instead we store
2022 extra data in their addend slot. Ignore the symbol. */
2023 switch (ELF64_R_TYPE (rel->r_info))
2024 {
2025 case R_ALPHA_LITUSE:
2026 case R_ALPHA_GPDISP:
2027 case R_ALPHA_HINT:
2028 return NULL;
2029 }
2030
2031 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
2032}
2033
Richard Hendersona7519a32005-05-26 07:14:03 +00002034/* Adjust a symbol defined by a dynamic object and referenced by a
2035 regular object. The current definition is in some section of the
2036 dynamic object, but we're not including those sections. We have to
2037 change the definition to something the rest of the link can
2038 understand. */
2039
Alan Modra0a1b45a2021-03-31 10:30:54 +10302040static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00002041elf64_alpha_adjust_dynamic_symbol (struct bfd_link_info *info,
2042 struct elf_link_hash_entry *h)
2043{
2044 bfd *dynobj;
2045 asection *s;
2046 struct alpha_elf_link_hash_entry *ah;
2047
2048 dynobj = elf_hash_table(info)->dynobj;
2049 ah = (struct alpha_elf_link_hash_entry *)h;
2050
2051 /* Now that we've seen all of the input symbols, finalize our decision
Richard Henderson6ec70572005-05-29 23:13:39 +00002052 about whether this symbol should get a .plt entry. Irritatingly, it
2053 is common for folk to leave undefined symbols in shared libraries,
2054 and they still expect lazy binding; accept undefined symbols in lieu
2055 of STT_FUNC. */
2056 if (alpha_elf_dynamic_symbol_p (h, info) && elf64_alpha_want_plt (ah))
Richard Hendersona7519a32005-05-26 07:14:03 +00002057 {
Alan Modra0a1b45a2021-03-31 10:30:54 +10302058 h->needs_plt = true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002059
Alan Modrace558b82016-11-23 15:06:34 +10302060 s = elf_hash_table(info)->splt;
Richard Hendersona7519a32005-05-26 07:14:03 +00002061 if (!s && !elf64_alpha_create_dynamic_sections (dynobj, info))
Alan Modra0a1b45a2021-03-31 10:30:54 +10302062 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00002063
Richard Henderson6ec70572005-05-29 23:13:39 +00002064 /* We need one plt entry per got subsection. Delay allocation of
2065 the actual plt entries until size_plt_section, called from
2066 size_dynamic_sections or during relaxation. */
Richard Hendersona7519a32005-05-26 07:14:03 +00002067
Alan Modra0a1b45a2021-03-31 10:30:54 +10302068 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002069 }
2070 else
Alan Modra0a1b45a2021-03-31 10:30:54 +10302071 h->needs_plt = false;
Richard Hendersona7519a32005-05-26 07:14:03 +00002072
2073 /* If this is a weak symbol, and there is a real definition, the
2074 processor independent code will have arranged for us to see the
2075 real definition first, and we can just use the same value. */
Alan Modra60d67dc2017-11-22 17:30:55 +10302076 if (h->is_weakalias)
Richard Hendersona7519a32005-05-26 07:14:03 +00002077 {
Alan Modra60d67dc2017-11-22 17:30:55 +10302078 struct elf_link_hash_entry *def = weakdef (h);
2079 BFD_ASSERT (def->root.type == bfd_link_hash_defined);
2080 h->root.u.def.section = def->root.u.def.section;
2081 h->root.u.def.value = def->root.u.def.value;
Alan Modra0a1b45a2021-03-31 10:30:54 +10302082 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002083 }
2084
2085 /* This is a reference to a symbol defined by a dynamic object which
2086 is not a function. The Alpha, since it uses .got entries for all
2087 symbols even in regular objects, does not need the hackery of a
2088 .dynbss section and COPY dynamic relocations. */
2089
Alan Modra0a1b45a2021-03-31 10:30:54 +10302090 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002091}
2092
Alan Modra747ffa72006-12-06 07:25:29 +00002093/* Record STO_ALPHA_NOPV and STO_ALPHA_STD_GPLOAD. */
2094
2095static void
2096elf64_alpha_merge_symbol_attribute (struct elf_link_hash_entry *h,
Alan Modra5160d0f2020-11-30 19:19:00 +10302097 unsigned int st_other,
Alan Modra0a1b45a2021-03-31 10:30:54 +10302098 bool definition,
2099 bool dynamic)
Alan Modra747ffa72006-12-06 07:25:29 +00002100{
2101 if (!dynamic && definition)
2102 h->other = ((h->other & ELF_ST_VISIBILITY (-1))
Alan Modra5160d0f2020-11-30 19:19:00 +10302103 | (st_other & ~ELF_ST_VISIBILITY (-1)));
Alan Modra747ffa72006-12-06 07:25:29 +00002104}
2105
Richard Hendersona7519a32005-05-26 07:14:03 +00002106/* Symbol versioning can create new symbols, and make our old symbols
2107 indirect to the new ones. Consolidate the got and reloc information
2108 in these situations. */
2109
Richard Henderson48f4b4f2011-06-15 15:04:12 +00002110static void
2111elf64_alpha_copy_indirect_symbol (struct bfd_link_info *info,
2112 struct elf_link_hash_entry *dir,
2113 struct elf_link_hash_entry *ind)
Richard Hendersona7519a32005-05-26 07:14:03 +00002114{
Richard Henderson48f4b4f2011-06-15 15:04:12 +00002115 struct alpha_elf_link_hash_entry *hi
2116 = (struct alpha_elf_link_hash_entry *) ind;
2117 struct alpha_elf_link_hash_entry *hs
2118 = (struct alpha_elf_link_hash_entry *) dir;
Richard Hendersona7519a32005-05-26 07:14:03 +00002119
Richard Henderson48f4b4f2011-06-15 15:04:12 +00002120 /* Do the merging in the superclass. */
2121 _bfd_elf_link_hash_copy_indirect(info, dir, ind);
Richard Hendersona7519a32005-05-26 07:14:03 +00002122
2123 /* Merge the flags. Whee. */
Richard Hendersona7519a32005-05-26 07:14:03 +00002124 hs->flags |= hi->flags;
2125
Richard Henderson48f4b4f2011-06-15 15:04:12 +00002126 /* ??? It's unclear to me what's really supposed to happen when
2127 "merging" defweak and defined symbols, given that we don't
2128 actually throw away the defweak. This more-or-less copies
2129 the logic related to got and plt entries in the superclass. */
2130 if (ind->root.type != bfd_link_hash_indirect)
2131 return;
2132
Richard Hendersona7519a32005-05-26 07:14:03 +00002133 /* Merge the .got entries. Cannibalize the old symbol's list in
2134 doing so, since we don't need it anymore. */
2135
2136 if (hs->got_entries == NULL)
2137 hs->got_entries = hi->got_entries;
2138 else
2139 {
2140 struct alpha_elf_got_entry *gi, *gs, *gin, *gsh;
2141
2142 gsh = hs->got_entries;
2143 for (gi = hi->got_entries; gi ; gi = gin)
2144 {
2145 gin = gi->next;
2146 for (gs = gsh; gs ; gs = gs->next)
2147 if (gi->gotobj == gs->gotobj
2148 && gi->reloc_type == gs->reloc_type
2149 && gi->addend == gs->addend)
2150 {
Jiaming Wei68994ca2016-08-09 16:18:42 +01002151 gs->use_count += gi->use_count;
Alan Modra07d6d2b2017-12-06 09:26:00 +10302152 goto got_found;
Richard Hendersona7519a32005-05-26 07:14:03 +00002153 }
2154 gi->next = hs->got_entries;
2155 hs->got_entries = gi;
2156 got_found:;
2157 }
2158 }
2159 hi->got_entries = NULL;
2160
2161 /* And similar for the reloc entries. */
2162
2163 if (hs->reloc_entries == NULL)
2164 hs->reloc_entries = hi->reloc_entries;
2165 else
2166 {
2167 struct alpha_elf_reloc_entry *ri, *rs, *rin, *rsh;
2168
2169 rsh = hs->reloc_entries;
2170 for (ri = hi->reloc_entries; ri ; ri = rin)
2171 {
2172 rin = ri->next;
2173 for (rs = rsh; rs ; rs = rs->next)
2174 if (ri->rtype == rs->rtype && ri->srel == rs->srel)
2175 {
2176 rs->count += ri->count;
2177 goto found_reloc;
2178 }
2179 ri->next = hs->reloc_entries;
2180 hs->reloc_entries = ri;
2181 found_reloc:;
2182 }
2183 }
2184 hi->reloc_entries = NULL;
Richard Hendersona7519a32005-05-26 07:14:03 +00002185}
2186
2187/* Is it possible to merge two object file's .got tables? */
2188
Alan Modra0a1b45a2021-03-31 10:30:54 +10302189static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00002190elf64_alpha_can_merge_gots (bfd *a, bfd *b)
2191{
2192 int total = alpha_elf_tdata (a)->total_got_size;
2193 bfd *bsub;
2194
2195 /* Trivial quick fallout test. */
2196 if (total + alpha_elf_tdata (b)->total_got_size <= MAX_GOT_SIZE)
Alan Modra0a1b45a2021-03-31 10:30:54 +10302197 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002198
2199 /* By their nature, local .got entries cannot be merged. */
2200 if ((total += alpha_elf_tdata (b)->local_got_size) > MAX_GOT_SIZE)
Alan Modra0a1b45a2021-03-31 10:30:54 +10302201 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00002202
2203 /* Failing the common trivial comparison, we must effectively
2204 perform the merge. Not actually performing the merge means that
2205 we don't have to store undo information in case we fail. */
2206 for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next)
2207 {
2208 struct alpha_elf_link_hash_entry **hashes = alpha_elf_sym_hashes (bsub);
2209 Elf_Internal_Shdr *symtab_hdr = &elf_tdata (bsub)->symtab_hdr;
2210 int i, n;
2211
2212 n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info;
2213 for (i = 0; i < n; ++i)
2214 {
2215 struct alpha_elf_got_entry *ae, *be;
2216 struct alpha_elf_link_hash_entry *h;
2217
2218 h = hashes[i];
2219 while (h->root.root.type == bfd_link_hash_indirect
Alan Modra07d6d2b2017-12-06 09:26:00 +10302220 || h->root.root.type == bfd_link_hash_warning)
Richard Hendersona7519a32005-05-26 07:14:03 +00002221 h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
2222
2223 for (be = h->got_entries; be ; be = be->next)
2224 {
2225 if (be->use_count == 0)
Alan Modra07d6d2b2017-12-06 09:26:00 +10302226 continue;
Richard Hendersona7519a32005-05-26 07:14:03 +00002227 if (be->gotobj != b)
Alan Modra07d6d2b2017-12-06 09:26:00 +10302228 continue;
Richard Hendersona7519a32005-05-26 07:14:03 +00002229
2230 for (ae = h->got_entries; ae ; ae = ae->next)
Alan Modra07d6d2b2017-12-06 09:26:00 +10302231 if (ae->gotobj == a
Richard Hendersona7519a32005-05-26 07:14:03 +00002232 && ae->reloc_type == be->reloc_type
2233 && ae->addend == be->addend)
2234 goto global_found;
2235
2236 total += alpha_got_entry_size (be->reloc_type);
2237 if (total > MAX_GOT_SIZE)
Alan Modra0a1b45a2021-03-31 10:30:54 +10302238 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00002239 global_found:;
2240 }
2241 }
2242 }
2243
Alan Modra0a1b45a2021-03-31 10:30:54 +10302244 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002245}
2246
2247/* Actually merge two .got tables. */
2248
2249static void
2250elf64_alpha_merge_gots (bfd *a, bfd *b)
2251{
2252 int total = alpha_elf_tdata (a)->total_got_size;
2253 bfd *bsub;
2254
2255 /* Remember local expansion. */
2256 {
2257 int e = alpha_elf_tdata (b)->local_got_size;
2258 total += e;
2259 alpha_elf_tdata (a)->local_got_size += e;
2260 }
2261
2262 for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next)
2263 {
2264 struct alpha_elf_got_entry **local_got_entries;
2265 struct alpha_elf_link_hash_entry **hashes;
2266 Elf_Internal_Shdr *symtab_hdr;
2267 int i, n;
2268
2269 /* Let the local .got entries know they are part of a new subsegment. */
2270 local_got_entries = alpha_elf_tdata (bsub)->local_got_entries;
2271 if (local_got_entries)
Alan Modra07d6d2b2017-12-06 09:26:00 +10302272 {
Richard Hendersona7519a32005-05-26 07:14:03 +00002273 n = elf_tdata (bsub)->symtab_hdr.sh_info;
2274 for (i = 0; i < n; ++i)
2275 {
2276 struct alpha_elf_got_entry *ent;
2277 for (ent = local_got_entries[i]; ent; ent = ent->next)
Alan Modra07d6d2b2017-12-06 09:26:00 +10302278 ent->gotobj = a;
Richard Hendersona7519a32005-05-26 07:14:03 +00002279 }
Alan Modra07d6d2b2017-12-06 09:26:00 +10302280 }
Richard Hendersona7519a32005-05-26 07:14:03 +00002281
2282 /* Merge the global .got entries. */
2283 hashes = alpha_elf_sym_hashes (bsub);
2284 symtab_hdr = &elf_tdata (bsub)->symtab_hdr;
2285
2286 n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info;
2287 for (i = 0; i < n; ++i)
Alan Modra07d6d2b2017-12-06 09:26:00 +10302288 {
Richard Hendersona7519a32005-05-26 07:14:03 +00002289 struct alpha_elf_got_entry *ae, *be, **pbe, **start;
2290 struct alpha_elf_link_hash_entry *h;
2291
2292 h = hashes[i];
2293 while (h->root.root.type == bfd_link_hash_indirect
Alan Modra07d6d2b2017-12-06 09:26:00 +10302294 || h->root.root.type == bfd_link_hash_warning)
Richard Hendersona7519a32005-05-26 07:14:03 +00002295 h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
2296
2297 pbe = start = &h->got_entries;
2298 while ((be = *pbe) != NULL)
2299 {
2300 if (be->use_count == 0)
Alan Modra07d6d2b2017-12-06 09:26:00 +10302301 {
Richard Hendersona7519a32005-05-26 07:14:03 +00002302 *pbe = be->next;
2303 memset (be, 0xa5, sizeof (*be));
2304 goto kill;
Alan Modra07d6d2b2017-12-06 09:26:00 +10302305 }
Richard Hendersona7519a32005-05-26 07:14:03 +00002306 if (be->gotobj != b)
Alan Modra07d6d2b2017-12-06 09:26:00 +10302307 goto next;
Richard Hendersona7519a32005-05-26 07:14:03 +00002308
2309 for (ae = *start; ae ; ae = ae->next)
Alan Modra07d6d2b2017-12-06 09:26:00 +10302310 if (ae->gotobj == a
Richard Hendersona7519a32005-05-26 07:14:03 +00002311 && ae->reloc_type == be->reloc_type
2312 && ae->addend == be->addend)
2313 {
2314 ae->flags |= be->flags;
2315 ae->use_count += be->use_count;
2316 *pbe = be->next;
2317 memset (be, 0xa5, sizeof (*be));
2318 goto kill;
2319 }
2320 be->gotobj = a;
2321 total += alpha_got_entry_size (be->reloc_type);
2322
2323 next:;
2324 pbe = &be->next;
2325 kill:;
2326 }
Alan Modra07d6d2b2017-12-06 09:26:00 +10302327 }
Richard Hendersona7519a32005-05-26 07:14:03 +00002328
2329 alpha_elf_tdata (bsub)->gotobj = a;
2330 }
2331 alpha_elf_tdata (a)->total_got_size = total;
2332
2333 /* Merge the two in_got chains. */
2334 {
2335 bfd *next;
2336
2337 bsub = a;
2338 while ((next = alpha_elf_tdata (bsub)->in_got_link_next) != NULL)
2339 bsub = next;
2340
2341 alpha_elf_tdata (bsub)->in_got_link_next = b;
2342 }
2343}
2344
2345/* Calculate the offsets for the got entries. */
2346
Alan Modra0a1b45a2021-03-31 10:30:54 +10302347static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00002348elf64_alpha_calc_got_offsets_for_symbol (struct alpha_elf_link_hash_entry *h,
Nick Clifton2c3fc382012-07-13 14:22:50 +00002349 void * arg ATTRIBUTE_UNUSED)
Richard Hendersona7519a32005-05-26 07:14:03 +00002350{
Richard Hendersona7519a32005-05-26 07:14:03 +00002351 struct alpha_elf_got_entry *gotent;
2352
Richard Hendersona7519a32005-05-26 07:14:03 +00002353 for (gotent = h->got_entries; gotent; gotent = gotent->next)
2354 if (gotent->use_count > 0)
2355 {
2356 struct alpha_elf_obj_tdata *td;
2357 bfd_size_type *plge;
2358
2359 td = alpha_elf_tdata (gotent->gotobj);
Richard Hendersona7519a32005-05-26 07:14:03 +00002360 plge = &td->got->size;
2361 gotent->got_offset = *plge;
2362 *plge += alpha_got_entry_size (gotent->reloc_type);
2363 }
2364
Alan Modra0a1b45a2021-03-31 10:30:54 +10302365 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002366}
2367
2368static void
2369elf64_alpha_calc_got_offsets (struct bfd_link_info *info)
2370{
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00002371 bfd *i, *got_list;
2372 struct alpha_elf_link_hash_table * htab;
2373
2374 htab = alpha_elf_hash_table (info);
2375 if (htab == NULL)
2376 return;
2377 got_list = htab->got_list;
Richard Hendersona7519a32005-05-26 07:14:03 +00002378
2379 /* First, zero out the .got sizes, as we may be recalculating the
2380 .got after optimizing it. */
2381 for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next)
2382 alpha_elf_tdata(i)->got->size = 0;
2383
2384 /* Next, fill in the offsets for all the global entries. */
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00002385 alpha_elf_link_hash_traverse (htab,
Richard Hendersona7519a32005-05-26 07:14:03 +00002386 elf64_alpha_calc_got_offsets_for_symbol,
2387 NULL);
2388
2389 /* Finally, fill in the offsets for the local entries. */
2390 for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next)
2391 {
2392 bfd_size_type got_offset = alpha_elf_tdata(i)->got->size;
2393 bfd *j;
2394
2395 for (j = i; j ; j = alpha_elf_tdata(j)->in_got_link_next)
2396 {
2397 struct alpha_elf_got_entry **local_got_entries, *gotent;
2398 int k, n;
2399
2400 local_got_entries = alpha_elf_tdata(j)->local_got_entries;
2401 if (!local_got_entries)
2402 continue;
2403
2404 for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k)
2405 for (gotent = local_got_entries[k]; gotent; gotent = gotent->next)
2406 if (gotent->use_count > 0)
Alan Modra07d6d2b2017-12-06 09:26:00 +10302407 {
Richard Hendersona7519a32005-05-26 07:14:03 +00002408 gotent->got_offset = got_offset;
2409 got_offset += alpha_got_entry_size (gotent->reloc_type);
Alan Modra07d6d2b2017-12-06 09:26:00 +10302410 }
Richard Hendersona7519a32005-05-26 07:14:03 +00002411 }
2412
2413 alpha_elf_tdata(i)->got->size = got_offset;
2414 }
2415}
2416
2417/* Constructs the gots. */
2418
Alan Modra0a1b45a2021-03-31 10:30:54 +10302419static bool
Richard Hendersond1c109d2014-04-21 08:14:18 -07002420elf64_alpha_size_got_sections (struct bfd_link_info *info,
Alan Modra0a1b45a2021-03-31 10:30:54 +10302421 bool may_merge)
Richard Hendersona7519a32005-05-26 07:14:03 +00002422{
2423 bfd *i, *got_list, *cur_got_obj = NULL;
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00002424 struct alpha_elf_link_hash_table * htab;
Richard Hendersona7519a32005-05-26 07:14:03 +00002425
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00002426 htab = alpha_elf_hash_table (info);
2427 if (htab == NULL)
Alan Modra0a1b45a2021-03-31 10:30:54 +10302428 return false;
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00002429 got_list = htab->got_list;
Richard Hendersona7519a32005-05-26 07:14:03 +00002430
2431 /* On the first time through, pretend we have an existing got list
2432 consisting of all of the input files. */
2433 if (got_list == NULL)
2434 {
Alan Modrac72f2fb2014-06-13 19:10:57 +09302435 for (i = info->input_bfds; i ; i = i->link.next)
Richard Hendersona7519a32005-05-26 07:14:03 +00002436 {
Nick Clifton0ffa91d2008-02-12 11:32:31 +00002437 bfd *this_got;
2438
2439 if (! is_alpha_elf (i))
2440 continue;
2441
2442 this_got = alpha_elf_tdata (i)->gotobj;
Richard Hendersona7519a32005-05-26 07:14:03 +00002443 if (this_got == NULL)
2444 continue;
2445
2446 /* We are assuming no merging has yet occurred. */
2447 BFD_ASSERT (this_got == i);
2448
Alan Modra07d6d2b2017-12-06 09:26:00 +10302449 if (alpha_elf_tdata (this_got)->total_got_size > MAX_GOT_SIZE)
Richard Hendersona7519a32005-05-26 07:14:03 +00002450 {
2451 /* Yikes! A single object file has too many entries. */
Alan Modra4eca0222016-09-30 13:00:18 +09302452 _bfd_error_handler
Nick Clifton695344c2016-10-19 14:04:34 +01002453 /* xgettext:c-format */
Alan Modra871b3ab2018-02-19 15:21:40 +10302454 (_("%pB: .got subsegment exceeds 64K (size %d)"),
Alan Modra07d6d2b2017-12-06 09:26:00 +10302455 i, alpha_elf_tdata (this_got)->total_got_size);
Alan Modra0a1b45a2021-03-31 10:30:54 +10302456 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00002457 }
2458
2459 if (got_list == NULL)
2460 got_list = this_got;
2461 else
2462 alpha_elf_tdata(cur_got_obj)->got_link_next = this_got;
2463 cur_got_obj = this_got;
2464 }
2465
2466 /* Strange degenerate case of no got references. */
2467 if (got_list == NULL)
Alan Modra0a1b45a2021-03-31 10:30:54 +10302468 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002469
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00002470 htab->got_list = got_list;
Richard Hendersona7519a32005-05-26 07:14:03 +00002471 }
2472
2473 cur_got_obj = got_list;
Nick Clifton0ffa91d2008-02-12 11:32:31 +00002474 if (cur_got_obj == NULL)
Alan Modra0a1b45a2021-03-31 10:30:54 +10302475 return false;
Nick Clifton0ffa91d2008-02-12 11:32:31 +00002476
Richard Hendersond1c109d2014-04-21 08:14:18 -07002477 if (may_merge)
Richard Hendersona7519a32005-05-26 07:14:03 +00002478 {
Richard Hendersond1c109d2014-04-21 08:14:18 -07002479 i = alpha_elf_tdata(cur_got_obj)->got_link_next;
2480 while (i != NULL)
Richard Hendersona7519a32005-05-26 07:14:03 +00002481 {
Richard Hendersond1c109d2014-04-21 08:14:18 -07002482 if (elf64_alpha_can_merge_gots (cur_got_obj, i))
2483 {
2484 elf64_alpha_merge_gots (cur_got_obj, i);
Richard Hendersona7519a32005-05-26 07:14:03 +00002485
Richard Hendersond1c109d2014-04-21 08:14:18 -07002486 alpha_elf_tdata(i)->got->size = 0;
2487 i = alpha_elf_tdata(i)->got_link_next;
2488 alpha_elf_tdata(cur_got_obj)->got_link_next = i;
2489 }
2490 else
2491 {
2492 cur_got_obj = i;
2493 i = alpha_elf_tdata(i)->got_link_next;
2494 }
Richard Hendersona7519a32005-05-26 07:14:03 +00002495 }
2496 }
2497
2498 /* Once the gots have been merged, fill in the got offsets for
2499 everything therein. */
Richard Henderson4a828aa2007-04-10 18:00:26 +00002500 elf64_alpha_calc_got_offsets (info);
Richard Hendersona7519a32005-05-26 07:14:03 +00002501
Alan Modra0a1b45a2021-03-31 10:30:54 +10302502 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002503}
2504
Alan Modra0a1b45a2021-03-31 10:30:54 +10302505static bool
Nick Clifton2c3fc382012-07-13 14:22:50 +00002506elf64_alpha_size_plt_section_1 (struct alpha_elf_link_hash_entry *h,
2507 void * data)
Richard Hendersona7519a32005-05-26 07:14:03 +00002508{
2509 asection *splt = (asection *) data;
2510 struct alpha_elf_got_entry *gotent;
Alan Modra0a1b45a2021-03-31 10:30:54 +10302511 bool saw_one = false;
Richard Hendersona7519a32005-05-26 07:14:03 +00002512
2513 /* If we didn't need an entry before, we still don't. */
2514 if (!h->root.needs_plt)
Alan Modra0a1b45a2021-03-31 10:30:54 +10302515 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002516
Richard Henderson6ec70572005-05-29 23:13:39 +00002517 /* For each LITERAL got entry still in use, allocate a plt entry. */
Richard Hendersona7519a32005-05-26 07:14:03 +00002518 for (gotent = h->got_entries; gotent ; gotent = gotent->next)
2519 if (gotent->reloc_type == R_ALPHA_LITERAL
2520 && gotent->use_count > 0)
Richard Henderson6ec70572005-05-29 23:13:39 +00002521 {
2522 if (splt->size == 0)
2523 splt->size = PLT_HEADER_SIZE;
2524 gotent->plt_offset = splt->size;
2525 splt->size += PLT_ENTRY_SIZE;
Alan Modra0a1b45a2021-03-31 10:30:54 +10302526 saw_one = true;
Richard Henderson6ec70572005-05-29 23:13:39 +00002527 }
Richard Hendersona7519a32005-05-26 07:14:03 +00002528
Richard Henderson6ec70572005-05-29 23:13:39 +00002529 /* If there weren't any, there's no longer a need for the PLT entry. */
2530 if (!saw_one)
Alan Modra0a1b45a2021-03-31 10:30:54 +10302531 h->root.needs_plt = false;
Richard Hendersona7519a32005-05-26 07:14:03 +00002532
Alan Modra0a1b45a2021-03-31 10:30:54 +10302533 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002534}
2535
Richard Henderson4a828aa2007-04-10 18:00:26 +00002536/* Called from relax_section to rebuild the PLT in light of potential changes
2537 in the function's status. */
Richard Hendersona7519a32005-05-26 07:14:03 +00002538
Richard Henderson4a828aa2007-04-10 18:00:26 +00002539static void
Richard Hendersona7519a32005-05-26 07:14:03 +00002540elf64_alpha_size_plt_section (struct bfd_link_info *info)
2541{
Richard Henderson6ec70572005-05-29 23:13:39 +00002542 asection *splt, *spltrel, *sgotplt;
Richard Hendersona7519a32005-05-26 07:14:03 +00002543 unsigned long entries;
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00002544 struct alpha_elf_link_hash_table * htab;
2545
2546 htab = alpha_elf_hash_table (info);
2547 if (htab == NULL)
2548 return;
Richard Hendersona7519a32005-05-26 07:14:03 +00002549
Alan Modrace558b82016-11-23 15:06:34 +10302550 splt = elf_hash_table(info)->splt;
Richard Hendersona7519a32005-05-26 07:14:03 +00002551 if (splt == NULL)
Richard Henderson4a828aa2007-04-10 18:00:26 +00002552 return;
Richard Hendersona7519a32005-05-26 07:14:03 +00002553
2554 splt->size = 0;
2555
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00002556 alpha_elf_link_hash_traverse (htab,
Richard Hendersona7519a32005-05-26 07:14:03 +00002557 elf64_alpha_size_plt_section_1, splt);
2558
2559 /* Every plt entry requires a JMP_SLOT relocation. */
Alan Modrace558b82016-11-23 15:06:34 +10302560 spltrel = elf_hash_table(info)->srelplt;
Richard Henderson4a828aa2007-04-10 18:00:26 +00002561 entries = 0;
Richard Hendersona7519a32005-05-26 07:14:03 +00002562 if (splt->size)
Richard Henderson6ec70572005-05-29 23:13:39 +00002563 {
2564 if (elf64_alpha_use_secureplt)
2565 entries = (splt->size - NEW_PLT_HEADER_SIZE) / NEW_PLT_ENTRY_SIZE;
2566 else
2567 entries = (splt->size - OLD_PLT_HEADER_SIZE) / OLD_PLT_ENTRY_SIZE;
2568 }
Richard Hendersona7519a32005-05-26 07:14:03 +00002569 spltrel->size = entries * sizeof (Elf64_External_Rela);
2570
Richard Henderson6ec70572005-05-29 23:13:39 +00002571 /* When using the secureplt, we need two words somewhere in the data
2572 segment for the dynamic linker to tell us where to go. This is the
2573 entire contents of the .got.plt section. */
2574 if (elf64_alpha_use_secureplt)
2575 {
Alan Modrace558b82016-11-23 15:06:34 +10302576 sgotplt = elf_hash_table(info)->sgotplt;
Richard Henderson6ec70572005-05-29 23:13:39 +00002577 sgotplt->size = entries ? 16 : 0;
2578 }
Richard Hendersona7519a32005-05-26 07:14:03 +00002579}
2580
Alan Modra0a1b45a2021-03-31 10:30:54 +10302581static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00002582elf64_alpha_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
2583 struct bfd_link_info *info)
2584{
2585 bfd *i;
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00002586 struct alpha_elf_link_hash_table * htab;
Richard Hendersona7519a32005-05-26 07:14:03 +00002587
H.J. Lu0e1862b2015-08-18 05:51:03 -07002588 if (bfd_link_relocatable (info))
Alan Modra0a1b45a2021-03-31 10:30:54 +10302589 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002590
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00002591 htab = alpha_elf_hash_table (info);
2592 if (htab == NULL)
Alan Modra0a1b45a2021-03-31 10:30:54 +10302593 return false;
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00002594
Alan Modra0a1b45a2021-03-31 10:30:54 +10302595 if (!elf64_alpha_size_got_sections (info, true))
2596 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00002597
2598 /* Allocate space for all of the .got subsections. */
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00002599 i = htab->got_list;
Richard Hendersona7519a32005-05-26 07:14:03 +00002600 for ( ; i ; i = alpha_elf_tdata(i)->got_link_next)
2601 {
2602 asection *s = alpha_elf_tdata(i)->got;
2603 if (s->size > 0)
2604 {
2605 s->contents = (bfd_byte *) bfd_zalloc (i, s->size);
2606 if (s->contents == NULL)
Alan Modra0a1b45a2021-03-31 10:30:54 +10302607 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00002608 }
2609 }
2610
Alan Modra0a1b45a2021-03-31 10:30:54 +10302611 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002612}
2613
2614/* The number of dynamic relocations required by a static relocation. */
2615
2616static int
Richard Hendersone366eea2011-06-22 16:18:24 +00002617alpha_dynamic_entries_for_reloc (int r_type, int dynamic, int shared, int pie)
Richard Hendersona7519a32005-05-26 07:14:03 +00002618{
2619 switch (r_type)
2620 {
2621 /* May appear in GOT entries. */
2622 case R_ALPHA_TLSGD:
2623 return (dynamic ? 2 : shared ? 1 : 0);
2624 case R_ALPHA_TLSLDM:
2625 return shared;
2626 case R_ALPHA_LITERAL:
Richard Hendersona7519a32005-05-26 07:14:03 +00002627 return dynamic || shared;
Richard Hendersone366eea2011-06-22 16:18:24 +00002628 case R_ALPHA_GOTTPREL:
2629 return dynamic || (shared && !pie);
Richard Hendersona7519a32005-05-26 07:14:03 +00002630 case R_ALPHA_GOTDTPREL:
2631 return dynamic;
2632
2633 /* May appear in data sections. */
2634 case R_ALPHA_REFLONG:
2635 case R_ALPHA_REFQUAD:
Richard Hendersona7519a32005-05-26 07:14:03 +00002636 return dynamic || shared;
Richard Hendersone366eea2011-06-22 16:18:24 +00002637 case R_ALPHA_TPREL64:
2638 return dynamic || (shared && !pie);
Richard Hendersona7519a32005-05-26 07:14:03 +00002639
2640 /* Everything else is illegal. We'll issue an error during
2641 relocate_section. */
2642 default:
2643 return 0;
2644 }
2645}
2646
2647/* Work out the sizes of the dynamic relocation entries. */
2648
Alan Modra0a1b45a2021-03-31 10:30:54 +10302649static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00002650elf64_alpha_calc_dynrel_sizes (struct alpha_elf_link_hash_entry *h,
2651 struct bfd_link_info *info)
2652{
Alan Modra0a1b45a2021-03-31 10:30:54 +10302653 bool dynamic;
Richard Hendersona7519a32005-05-26 07:14:03 +00002654 struct alpha_elf_reloc_entry *relent;
2655 unsigned long entries;
2656
Richard Hendersona7519a32005-05-26 07:14:03 +00002657 /* If the symbol was defined as a common symbol in a regular object
2658 file, and there was no definition in any dynamic object, then the
2659 linker will have allocated space for the symbol in a common
2660 section but the ELF_LINK_HASH_DEF_REGULAR flag will not have been
2661 set. This is done for dynamic symbols in
2662 elf_adjust_dynamic_symbol but this is not done for non-dynamic
2663 symbols, somehow. */
2664 if (!h->root.def_regular
2665 && h->root.ref_regular
2666 && !h->root.def_dynamic
2667 && (h->root.root.type == bfd_link_hash_defined
2668 || h->root.root.type == bfd_link_hash_defweak)
2669 && !(h->root.root.u.def.section->owner->flags & DYNAMIC))
2670 h->root.def_regular = 1;
2671
2672 /* If the symbol is dynamic, we'll need all the relocations in their
2673 natural form. If this is a shared object, and it has been forced
2674 local, we'll need the same number of RELATIVE relocations. */
2675 dynamic = alpha_elf_dynamic_symbol_p (&h->root, info);
2676
2677 /* If the symbol is a hidden undefined weak, then we never have any
2678 relocations. Avoid the loop which may want to add RELATIVE relocs
H.J. Lu0e1862b2015-08-18 05:51:03 -07002679 based on bfd_link_pic (info). */
Richard Hendersona7519a32005-05-26 07:14:03 +00002680 if (h->root.root.type == bfd_link_hash_undefweak && !dynamic)
Alan Modra0a1b45a2021-03-31 10:30:54 +10302681 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002682
2683 for (relent = h->reloc_entries; relent; relent = relent->next)
2684 {
2685 entries = alpha_dynamic_entries_for_reloc (relent->rtype, dynamic,
Alan Modra3cbc1e52015-08-19 11:57:40 +09302686 bfd_link_pic (info),
2687 bfd_link_pie (info));
Richard Hendersona7519a32005-05-26 07:14:03 +00002688 if (entries)
2689 {
H.J. Lu1f7f2ab2020-04-21 05:20:11 -07002690 asection *sec = relent->sec;
Richard Hendersona7519a32005-05-26 07:14:03 +00002691 relent->srel->size +=
2692 entries * sizeof (Elf64_External_Rela) * relent->count;
H.J. Lu1f7f2ab2020-04-21 05:20:11 -07002693 if ((sec->flags & SEC_READONLY) != 0)
2694 {
2695 info->flags |= DT_TEXTREL;
2696 info->callbacks->minfo
2697 (_("%pB: dynamic relocation against `%pT' in "
2698 "read-only section `%pA'\n"),
2699 sec->owner, h->root.root.root.string, sec);
2700 }
Richard Hendersona7519a32005-05-26 07:14:03 +00002701 }
2702 }
2703
Alan Modra0a1b45a2021-03-31 10:30:54 +10302704 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002705}
2706
2707/* Subroutine of elf64_alpha_size_rela_got_section for doing the
2708 global symbols. */
2709
Alan Modra0a1b45a2021-03-31 10:30:54 +10302710static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00002711elf64_alpha_size_rela_got_1 (struct alpha_elf_link_hash_entry *h,
2712 struct bfd_link_info *info)
2713{
Alan Modra0a1b45a2021-03-31 10:30:54 +10302714 bool dynamic;
Richard Hendersona7519a32005-05-26 07:14:03 +00002715 struct alpha_elf_got_entry *gotent;
2716 unsigned long entries;
2717
Richard Henderson6ec70572005-05-29 23:13:39 +00002718 /* If we're using a plt for this symbol, then all of its relocations
2719 for its got entries go into .rela.plt. */
2720 if (h->root.needs_plt)
Alan Modra0a1b45a2021-03-31 10:30:54 +10302721 return true;
Richard Henderson6ec70572005-05-29 23:13:39 +00002722
Richard Hendersona7519a32005-05-26 07:14:03 +00002723 /* If the symbol is dynamic, we'll need all the relocations in their
2724 natural form. If this is a shared object, and it has been forced
2725 local, we'll need the same number of RELATIVE relocations. */
2726 dynamic = alpha_elf_dynamic_symbol_p (&h->root, info);
2727
2728 /* If the symbol is a hidden undefined weak, then we never have any
2729 relocations. Avoid the loop which may want to add RELATIVE relocs
H.J. Lu0e1862b2015-08-18 05:51:03 -07002730 based on bfd_link_pic (info). */
Richard Hendersona7519a32005-05-26 07:14:03 +00002731 if (h->root.root.type == bfd_link_hash_undefweak && !dynamic)
Alan Modra0a1b45a2021-03-31 10:30:54 +10302732 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002733
2734 entries = 0;
2735 for (gotent = h->got_entries; gotent ; gotent = gotent->next)
2736 if (gotent->use_count > 0)
Richard Hendersone366eea2011-06-22 16:18:24 +00002737 entries += alpha_dynamic_entries_for_reloc (gotent->reloc_type, dynamic,
H.J. Lu0e1862b2015-08-18 05:51:03 -07002738 bfd_link_pic (info),
2739 bfd_link_pie (info));
Richard Hendersona7519a32005-05-26 07:14:03 +00002740
Richard Hendersona7519a32005-05-26 07:14:03 +00002741 if (entries > 0)
2742 {
Alan Modrace558b82016-11-23 15:06:34 +10302743 asection *srel = elf_hash_table(info)->srelgot;
Richard Hendersona7519a32005-05-26 07:14:03 +00002744 BFD_ASSERT (srel != NULL);
2745 srel->size += sizeof (Elf64_External_Rela) * entries;
2746 }
2747
Alan Modra0a1b45a2021-03-31 10:30:54 +10302748 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002749}
2750
2751/* Set the sizes of the dynamic relocation sections. */
2752
Richard Henderson4a828aa2007-04-10 18:00:26 +00002753static void
Richard Hendersona7519a32005-05-26 07:14:03 +00002754elf64_alpha_size_rela_got_section (struct bfd_link_info *info)
2755{
2756 unsigned long entries;
Alan Modrace558b82016-11-23 15:06:34 +10302757 bfd *i;
Richard Hendersona7519a32005-05-26 07:14:03 +00002758 asection *srel;
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00002759 struct alpha_elf_link_hash_table * htab;
2760
2761 htab = alpha_elf_hash_table (info);
2762 if (htab == NULL)
2763 return;
Richard Hendersona7519a32005-05-26 07:14:03 +00002764
2765 /* Shared libraries often require RELATIVE relocs, and some relocs
2766 require attention for the main application as well. */
2767
2768 entries = 0;
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00002769 for (i = htab->got_list;
Richard Hendersona7519a32005-05-26 07:14:03 +00002770 i ; i = alpha_elf_tdata(i)->got_link_next)
2771 {
2772 bfd *j;
2773
2774 for (j = i; j ; j = alpha_elf_tdata(j)->in_got_link_next)
2775 {
2776 struct alpha_elf_got_entry **local_got_entries, *gotent;
2777 int k, n;
2778
2779 local_got_entries = alpha_elf_tdata(j)->local_got_entries;
2780 if (!local_got_entries)
2781 continue;
2782
2783 for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k)
2784 for (gotent = local_got_entries[k];
2785 gotent ; gotent = gotent->next)
2786 if (gotent->use_count > 0)
2787 entries += (alpha_dynamic_entries_for_reloc
H.J. Lu0e1862b2015-08-18 05:51:03 -07002788 (gotent->reloc_type, 0, bfd_link_pic (info),
2789 bfd_link_pie (info)));
Richard Hendersona7519a32005-05-26 07:14:03 +00002790 }
2791 }
2792
Alan Modrace558b82016-11-23 15:06:34 +10302793 srel = elf_hash_table(info)->srelgot;
Richard Hendersona7519a32005-05-26 07:14:03 +00002794 if (!srel)
2795 {
2796 BFD_ASSERT (entries == 0);
Richard Henderson4a828aa2007-04-10 18:00:26 +00002797 return;
Richard Hendersona7519a32005-05-26 07:14:03 +00002798 }
2799 srel->size = sizeof (Elf64_External_Rela) * entries;
2800
2801 /* Now do the non-local symbols. */
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00002802 alpha_elf_link_hash_traverse (htab,
Richard Hendersona7519a32005-05-26 07:14:03 +00002803 elf64_alpha_size_rela_got_1, info);
Richard Hendersona7519a32005-05-26 07:14:03 +00002804}
2805
2806/* Set the sizes of the dynamic sections. */
2807
Alan Modra0a1b45a2021-03-31 10:30:54 +10302808static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00002809elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
2810 struct bfd_link_info *info)
2811{
2812 bfd *dynobj;
2813 asection *s;
Alan Modra0a1b45a2021-03-31 10:30:54 +10302814 bool relplt, relocs;
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00002815 struct alpha_elf_link_hash_table * htab;
2816
2817 htab = alpha_elf_hash_table (info);
2818 if (htab == NULL)
Alan Modra0a1b45a2021-03-31 10:30:54 +10302819 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00002820
2821 dynobj = elf_hash_table(info)->dynobj;
2822 BFD_ASSERT(dynobj != NULL);
2823
2824 if (elf_hash_table (info)->dynamic_sections_created)
2825 {
2826 /* Set the contents of the .interp section to the interpreter. */
Rich Felker9b8b3252015-09-20 12:20:19 +09302827 if (bfd_link_executable (info) && !info->nointerp)
Richard Hendersona7519a32005-05-26 07:14:03 +00002828 {
Alan Modra3d4d4302012-06-29 14:46:03 +00002829 s = bfd_get_linker_section (dynobj, ".interp");
Richard Hendersona7519a32005-05-26 07:14:03 +00002830 BFD_ASSERT (s != NULL);
2831 s->size = sizeof ELF_DYNAMIC_INTERPRETER;
2832 s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
2833 }
2834
2835 /* Now that we've seen all of the input files, we can decide which
2836 symbols need dynamic relocation entries and which don't. We've
2837 collected information in check_relocs that we can now apply to
2838 size the dynamic relocation sections. */
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00002839 alpha_elf_link_hash_traverse (htab,
Richard Hendersona7519a32005-05-26 07:14:03 +00002840 elf64_alpha_calc_dynrel_sizes, info);
2841
2842 elf64_alpha_size_rela_got_section (info);
Richard Henderson6ec70572005-05-29 23:13:39 +00002843 elf64_alpha_size_plt_section (info);
Richard Hendersona7519a32005-05-26 07:14:03 +00002844 }
2845 /* else we're not dynamic and by definition we don't need such things. */
2846
2847 /* The check_relocs and adjust_dynamic_symbol entry points have
2848 determined the sizes of the various dynamic sections. Allocate
2849 memory for them. */
Alan Modra0a1b45a2021-03-31 10:30:54 +10302850 relplt = false;
2851 relocs = false;
Richard Hendersona7519a32005-05-26 07:14:03 +00002852 for (s = dynobj->sections; s != NULL; s = s->next)
2853 {
2854 const char *name;
Richard Hendersona7519a32005-05-26 07:14:03 +00002855
2856 if (!(s->flags & SEC_LINKER_CREATED))
2857 continue;
2858
2859 /* It's OK to base decisions on the section name, because none
2860 of the dynobj section names depend upon the input files. */
Alan Modrafd361982019-09-16 20:25:17 +09302861 name = bfd_section_name (s);
Richard Hendersona7519a32005-05-26 07:14:03 +00002862
Martin Liska08dedd62021-03-19 11:50:26 +01002863 if (startswith (name, ".rela"))
Richard Hendersona7519a32005-05-26 07:14:03 +00002864 {
Alan Modrac456f082005-07-08 06:20:06 +00002865 if (s->size != 0)
Richard Hendersona7519a32005-05-26 07:14:03 +00002866 {
Alan Modrac456f082005-07-08 06:20:06 +00002867 if (strcmp (name, ".rela.plt") == 0)
Alan Modra0a1b45a2021-03-31 10:30:54 +10302868 relplt = true;
Alan Modra24f1a752017-02-20 17:57:43 +10302869 else
Alan Modra0a1b45a2021-03-31 10:30:54 +10302870 relocs = true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002871
2872 /* We use the reloc_count field as a counter if we need
2873 to copy relocs into the output file. */
2874 s->reloc_count = 0;
2875 }
2876 }
Martin Liska08dedd62021-03-19 11:50:26 +01002877 else if (! startswith (name, ".got")
Alan Modrac456f082005-07-08 06:20:06 +00002878 && strcmp (name, ".plt") != 0
2879 && strcmp (name, ".dynbss") != 0)
Richard Hendersona7519a32005-05-26 07:14:03 +00002880 {
2881 /* It's not one of our dynamic sections, so don't allocate space. */
2882 continue;
2883 }
2884
Alan Modrac456f082005-07-08 06:20:06 +00002885 if (s->size == 0)
2886 {
2887 /* If we don't need this section, strip it from the output file.
2888 This is to handle .rela.bss and .rela.plt. We must create it
2889 in create_dynamic_sections, because it must be created before
2890 the linker maps input sections to output sections. The
2891 linker does that before adjust_dynamic_symbol is called, and
2892 it is that function which decides whether anything needs to
2893 go into these sections. */
Martin Liska08dedd62021-03-19 11:50:26 +01002894 if (!startswith (name, ".got"))
Richard Henderson6452a562011-04-12 23:23:02 +00002895 s->flags |= SEC_EXCLUDE;
Alan Modrac456f082005-07-08 06:20:06 +00002896 }
2897 else if ((s->flags & SEC_HAS_CONTENTS) != 0)
Richard Hendersona7519a32005-05-26 07:14:03 +00002898 {
2899 /* Allocate memory for the section contents. */
2900 s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
Alan Modrac456f082005-07-08 06:20:06 +00002901 if (s->contents == NULL)
Alan Modra0a1b45a2021-03-31 10:30:54 +10302902 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00002903 }
2904 }
2905
2906 if (elf_hash_table (info)->dynamic_sections_created)
2907 {
2908 /* Add some entries to the .dynamic section. We fill in the
2909 values later, in elf64_alpha_finish_dynamic_sections, but we
2910 must add the entries now so that we get the correct size for
2911 the .dynamic section. The DT_DEBUG entry is filled in by the
2912 dynamic linker and used by the debugger. */
2913#define add_dynamic_entry(TAG, VAL) \
2914 _bfd_elf_add_dynamic_entry (info, TAG, VAL)
2915
H.J. Lu3084d7a2020-06-23 05:07:31 -07002916 if (!_bfd_elf_add_dynamic_tags (output_bfd, info,
2917 relocs || relplt))
Alan Modra0a1b45a2021-03-31 10:30:54 +10302918 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00002919
H.J. Lu3084d7a2020-06-23 05:07:31 -07002920 if (relplt
2921 && elf64_alpha_use_secureplt
2922 && !add_dynamic_entry (DT_ALPHA_PLTRO, 1))
Alan Modra0a1b45a2021-03-31 10:30:54 +10302923 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00002924 }
2925#undef add_dynamic_entry
2926
Alan Modra0a1b45a2021-03-31 10:30:54 +10302927 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002928}
2929
Kazu Hiratafe8bc632000-12-09 01:54:51 +00002930/* These functions do relaxation for Alpha ELF.
Richard Henderson252b5131999-05-03 07:29:11 +00002931
2932 Currently I'm only handling what I can do with existing compiler
2933 and assembler support, which means no instructions are removed,
2934 though some may be nopped. At this time GCC does not emit enough
2935 information to do all of the relaxing that is possible. It will
2936 take some not small amount of work for that to happen.
2937
2938 There are a couple of interesting papers that I once read on this
2939 subject, that I cannot find references to at the moment, that
2940 related to Alpha in particular. They are by David Wall, then of
2941 DEC WRL. */
2942
Richard Henderson252b5131999-05-03 07:29:11 +00002943struct alpha_relax_info
2944{
2945 bfd *abfd;
2946 asection *sec;
2947 bfd_byte *contents;
Richard Henderson9e756d62002-06-02 02:28:45 +00002948 Elf_Internal_Shdr *symtab_hdr;
Richard Henderson252b5131999-05-03 07:29:11 +00002949 Elf_Internal_Rela *relocs, *relend;
2950 struct bfd_link_info *link_info;
Richard Henderson252b5131999-05-03 07:29:11 +00002951 bfd_vma gp;
2952 bfd *gotobj;
2953 asection *tsec;
2954 struct alpha_elf_link_hash_entry *h;
Richard Henderson9e756d62002-06-02 02:28:45 +00002955 struct alpha_elf_got_entry **first_gotent;
Richard Henderson252b5131999-05-03 07:29:11 +00002956 struct alpha_elf_got_entry *gotent;
Alan Modra0a1b45a2021-03-31 10:30:54 +10302957 bool changed_contents;
2958 bool changed_relocs;
Richard Henderson252b5131999-05-03 07:29:11 +00002959 unsigned char other;
2960};
2961
Richard Henderson252b5131999-05-03 07:29:11 +00002962static Elf_Internal_Rela *
Richard Hendersona7519a32005-05-26 07:14:03 +00002963elf64_alpha_find_reloc_at_ofs (Elf_Internal_Rela *rel,
2964 Elf_Internal_Rela *relend,
2965 bfd_vma offset, int type)
Richard Henderson252b5131999-05-03 07:29:11 +00002966{
2967 while (rel < relend)
2968 {
Alan Modra52b9d212001-08-17 09:19:10 +00002969 if (rel->r_offset == offset
2970 && ELF64_R_TYPE (rel->r_info) == (unsigned int) type)
Richard Henderson252b5131999-05-03 07:29:11 +00002971 return rel;
2972 ++rel;
2973 }
2974 return NULL;
2975}
2976
Alan Modra0a1b45a2021-03-31 10:30:54 +10302977static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00002978elf64_alpha_relax_got_load (struct alpha_relax_info *info, bfd_vma symval,
2979 Elf_Internal_Rela *irel, unsigned long r_type)
2980{
2981 unsigned int insn;
2982 bfd_signed_vma disp;
2983
2984 /* Get the instruction. */
2985 insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset);
2986
2987 if (insn >> 26 != OP_LDQ)
2988 {
2989 reloc_howto_type *howto = elf64_alpha_howto_table + r_type;
Alan Modra4eca0222016-09-30 13:00:18 +09302990 _bfd_error_handler
Nick Clifton695344c2016-10-19 14:04:34 +01002991 /* xgettext:c-format */
Alan Modra2dcf00c2018-02-19 18:34:15 +10302992 (_("%pB: %pA+%#" PRIx64 ": warning: "
2993 "%s relocation against unexpected insn"),
2994 info->abfd, info->sec, (uint64_t) irel->r_offset, howto->name);
Alan Modra0a1b45a2021-03-31 10:30:54 +10302995 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00002996 }
2997
2998 /* Can't relax dynamic symbols. */
Nick Cliftoneae0b5c2020-08-26 16:26:13 +01002999 if (info->h != NULL
3000 && alpha_elf_dynamic_symbol_p (&info->h->root, info->link_info))
Alan Modra0a1b45a2021-03-31 10:30:54 +10303001 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00003002
3003 /* Can't use local-exec relocations in shared libraries. */
Richard Hendersone366eea2011-06-22 16:18:24 +00003004 if (r_type == R_ALPHA_GOTTPREL
Alan Modra3cbc1e52015-08-19 11:57:40 +09303005 && bfd_link_dll (info->link_info))
Alan Modra0a1b45a2021-03-31 10:30:54 +10303006 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00003007
3008 if (r_type == R_ALPHA_LITERAL)
3009 {
3010 /* Look for nice constant addresses. This includes the not-uncommon
3011 special case of 0 for undefweak symbols. */
3012 if ((info->h && info->h->root.root.type == bfd_link_hash_undefweak)
H.J. Lu0e1862b2015-08-18 05:51:03 -07003013 || (!bfd_link_pic (info->link_info)
Richard Hendersona7519a32005-05-26 07:14:03 +00003014 && (symval >= (bfd_vma)-0x8000 || symval < 0x8000)))
3015 {
3016 disp = 0;
3017 insn = (OP_LDA << 26) | (insn & (31 << 21)) | (31 << 16);
3018 insn |= (symval & 0xffff);
3019 r_type = R_ALPHA_NONE;
3020 }
3021 else
3022 {
Richard Hendersond1c109d2014-04-21 08:14:18 -07003023 /* We may only create GPREL relocs during the second pass. */
3024 if (info->link_info->relax_pass == 0)
Alan Modra0a1b45a2021-03-31 10:30:54 +10303025 return true;
Richard Hendersond1c109d2014-04-21 08:14:18 -07003026
Richard Hendersona7519a32005-05-26 07:14:03 +00003027 disp = symval - info->gp;
3028 insn = (OP_LDA << 26) | (insn & 0x03ff0000);
3029 r_type = R_ALPHA_GPREL16;
3030 }
3031 }
3032 else
3033 {
3034 bfd_vma dtp_base, tp_base;
3035
3036 BFD_ASSERT (elf_hash_table (info->link_info)->tls_sec != NULL);
3037 dtp_base = alpha_get_dtprel_base (info->link_info);
3038 tp_base = alpha_get_tprel_base (info->link_info);
3039 disp = symval - (r_type == R_ALPHA_GOTDTPREL ? dtp_base : tp_base);
3040
3041 insn = (OP_LDA << 26) | (insn & (31 << 21)) | (31 << 16);
3042
3043 switch (r_type)
3044 {
3045 case R_ALPHA_GOTDTPREL:
3046 r_type = R_ALPHA_DTPREL16;
3047 break;
3048 case R_ALPHA_GOTTPREL:
3049 r_type = R_ALPHA_TPREL16;
3050 break;
3051 default:
3052 BFD_ASSERT (0);
Alan Modra0a1b45a2021-03-31 10:30:54 +10303053 return false;
Richard Hendersona7519a32005-05-26 07:14:03 +00003054 }
3055 }
3056
3057 if (disp < -0x8000 || disp >= 0x8000)
Alan Modra0a1b45a2021-03-31 10:30:54 +10303058 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00003059
3060 bfd_put_32 (info->abfd, (bfd_vma) insn, info->contents + irel->r_offset);
Alan Modra0a1b45a2021-03-31 10:30:54 +10303061 info->changed_contents = true;
Richard Hendersona7519a32005-05-26 07:14:03 +00003062
3063 /* Reduce the use count on this got entry by one, possibly
3064 eliminating it. */
3065 if (--info->gotent->use_count == 0)
3066 {
3067 int sz = alpha_got_entry_size (r_type);
3068 alpha_elf_tdata (info->gotobj)->total_got_size -= sz;
3069 if (!info->h)
3070 alpha_elf_tdata (info->gotobj)->local_got_size -= sz;
3071 }
3072
3073 /* Smash the existing GOT relocation for its 16-bit immediate pair. */
3074 irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), r_type);
Alan Modra0a1b45a2021-03-31 10:30:54 +10303075 info->changed_relocs = true;
Richard Hendersona7519a32005-05-26 07:14:03 +00003076
3077 /* ??? Search forward through this basic block looking for insns
3078 that use the target register. Stop after an insn modifying the
3079 register is seen, or after a branch or call.
3080
3081 Any such memory load insn may be substituted by a load directly
3082 off the GP. This allows the memory load insn to be issued before
3083 the calculated GP register would otherwise be ready.
3084
3085 Any such jsr insn can be replaced by a bsr if it is in range.
3086
3087 This would mean that we'd have to _add_ relocations, the pain of
3088 which gives one pause. */
3089
Alan Modra0a1b45a2021-03-31 10:30:54 +10303090 return true;
Richard Hendersona7519a32005-05-26 07:14:03 +00003091}
3092
3093static bfd_vma
3094elf64_alpha_relax_opt_call (struct alpha_relax_info *info, bfd_vma symval)
3095{
3096 /* If the function has the same gp, and we can identify that the
3097 function does not use its function pointer, we can eliminate the
3098 address load. */
3099
3100 /* If the symbol is marked NOPV, we are being told the function never
3101 needs its procedure value. */
3102 if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_NOPV)
3103 return symval;
3104
3105 /* If the symbol is marked STD_GP, we are being told the function does
3106 a normal ldgp in the first two words. */
3107 else if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_STD_GPLOAD)
3108 ;
3109
3110 /* Otherwise, we may be able to identify a GP load in the first two
3111 words, which we can then skip. */
3112 else
3113 {
3114 Elf_Internal_Rela *tsec_relocs, *tsec_relend, *tsec_free, *gpdisp;
3115 bfd_vma ofs;
3116
3117 /* Load the relocations from the section that the target symbol is in. */
3118 if (info->sec == info->tsec)
3119 {
3120 tsec_relocs = info->relocs;
3121 tsec_relend = info->relend;
3122 tsec_free = NULL;
3123 }
3124 else
3125 {
3126 tsec_relocs = (_bfd_elf_link_read_relocs
Alan Modra07d6d2b2017-12-06 09:26:00 +10303127 (info->abfd, info->tsec, NULL,
Richard Hendersona7519a32005-05-26 07:14:03 +00003128 (Elf_Internal_Rela *) NULL,
3129 info->link_info->keep_memory));
3130 if (tsec_relocs == NULL)
3131 return 0;
3132 tsec_relend = tsec_relocs + info->tsec->reloc_count;
James Clarkeae4fda62017-01-03 16:15:15 +00003133 tsec_free = (elf_section_data (info->tsec)->relocs == tsec_relocs
3134 ? NULL
3135 : tsec_relocs);
Richard Hendersona7519a32005-05-26 07:14:03 +00003136 }
3137
3138 /* Recover the symbol's offset within the section. */
3139 ofs = (symval - info->tsec->output_section->vma
3140 - info->tsec->output_offset);
3141
3142 /* Look for a GPDISP reloc. */
3143 gpdisp = (elf64_alpha_find_reloc_at_ofs
3144 (tsec_relocs, tsec_relend, ofs, R_ALPHA_GPDISP));
3145
3146 if (!gpdisp || gpdisp->r_addend != 4)
3147 {
Alan Modrac9594982020-05-20 17:25:20 +09303148 free (tsec_free);
Richard Hendersona7519a32005-05-26 07:14:03 +00003149 return 0;
3150 }
Alan Modrac9594982020-05-20 17:25:20 +09303151 free (tsec_free);
Richard Hendersona7519a32005-05-26 07:14:03 +00003152 }
3153
3154 /* We've now determined that we can skip an initial gp load. Verify
3155 that the call and the target use the same gp. */
Alan Modraf13a99d2008-02-15 03:35:53 +00003156 if (info->link_info->output_bfd->xvec != info->tsec->owner->xvec
Richard Hendersona7519a32005-05-26 07:14:03 +00003157 || info->gotobj != alpha_elf_tdata (info->tsec->owner)->gotobj)
3158 return 0;
3159
3160 return symval + 8;
3161}
3162
Alan Modra0a1b45a2021-03-31 10:30:54 +10303163static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00003164elf64_alpha_relax_with_lituse (struct alpha_relax_info *info,
3165 bfd_vma symval, Elf_Internal_Rela *irel)
Richard Henderson252b5131999-05-03 07:29:11 +00003166{
Richard Hendersond1c109d2014-04-21 08:14:18 -07003167 Elf_Internal_Rela *urel, *erel, *irelend = info->relend;
3168 int flags;
Richard Henderson252b5131999-05-03 07:29:11 +00003169 bfd_signed_vma disp;
Alan Modra0a1b45a2021-03-31 10:30:54 +10303170 bool fits16;
3171 bool fits32;
3172 bool lit_reused = false;
3173 bool all_optimized = true;
3174 bool changed_contents;
3175 bool changed_relocs;
Richard Hendersond1c109d2014-04-21 08:14:18 -07003176 bfd_byte *contents = info->contents;
3177 bfd *abfd = info->abfd;
3178 bfd_vma sec_output_vma;
Richard Henderson252b5131999-05-03 07:29:11 +00003179 unsigned int lit_insn;
Richard Hendersond1c109d2014-04-21 08:14:18 -07003180 int relax_pass;
Richard Henderson252b5131999-05-03 07:29:11 +00003181
Richard Hendersond1c109d2014-04-21 08:14:18 -07003182 lit_insn = bfd_get_32 (abfd, contents + irel->r_offset);
Richard Henderson252b5131999-05-03 07:29:11 +00003183 if (lit_insn >> 26 != OP_LDQ)
3184 {
Alan Modra4eca0222016-09-30 13:00:18 +09303185 _bfd_error_handler
Nick Clifton695344c2016-10-19 14:04:34 +01003186 /* xgettext:c-format */
Alan Modra2dcf00c2018-02-19 18:34:15 +10303187 (_("%pB: %pA+%#" PRIx64 ": warning: "
Alan Modra38f14ab2018-02-21 13:09:46 +10303188 "%s relocation against unexpected insn"),
3189 abfd, info->sec, (uint64_t) irel->r_offset, "LITERAL");
Alan Modra0a1b45a2021-03-31 10:30:54 +10303190 return true;
Richard Henderson252b5131999-05-03 07:29:11 +00003191 }
3192
Richard Henderson9e756d62002-06-02 02:28:45 +00003193 /* Can't relax dynamic symbols. */
Alan Modraf2cfdb72021-09-03 08:18:15 +09303194 if (info->h != NULL
3195 && alpha_elf_dynamic_symbol_p (&info->h->root, info->link_info))
Alan Modra0a1b45a2021-03-31 10:30:54 +10303196 return true;
Richard Henderson9e756d62002-06-02 02:28:45 +00003197
Richard Hendersond1c109d2014-04-21 08:14:18 -07003198 changed_contents = info->changed_contents;
3199 changed_relocs = info->changed_relocs;
3200 sec_output_vma = info->sec->output_section->vma + info->sec->output_offset;
3201 relax_pass = info->link_info->relax_pass;
3202
Richard Henderson252b5131999-05-03 07:29:11 +00003203 /* Summarize how this particular LITERAL is used. */
Richard Hendersond1c109d2014-04-21 08:14:18 -07003204 for (erel = irel+1, flags = 0; erel < irelend; ++erel)
Richard Henderson252b5131999-05-03 07:29:11 +00003205 {
Richard Hendersond1c109d2014-04-21 08:14:18 -07003206 if (ELF64_R_TYPE (erel->r_info) != R_ALPHA_LITUSE)
Richard Henderson252b5131999-05-03 07:29:11 +00003207 break;
Richard Hendersond1c109d2014-04-21 08:14:18 -07003208 if (erel->r_addend <= 6)
3209 flags |= 1 << erel->r_addend;
Richard Henderson252b5131999-05-03 07:29:11 +00003210 }
3211
Kazu Hiratafe8bc632000-12-09 01:54:51 +00003212 /* A little preparation for the loop... */
Richard Henderson252b5131999-05-03 07:29:11 +00003213 disp = symval - info->gp;
Richard Henderson252b5131999-05-03 07:29:11 +00003214
Richard Hendersond1c109d2014-04-21 08:14:18 -07003215 for (urel = irel+1; urel < erel; ++urel)
Richard Henderson252b5131999-05-03 07:29:11 +00003216 {
Richard Hendersond1c109d2014-04-21 08:14:18 -07003217 bfd_vma urel_r_offset = urel->r_offset;
Richard Henderson252b5131999-05-03 07:29:11 +00003218 unsigned int insn;
Nick Cliftonffcb7af2000-09-15 18:07:28 +00003219 int insn_disp;
3220 bfd_signed_vma xdisp;
Richard Hendersond1c109d2014-04-21 08:14:18 -07003221 Elf_Internal_Rela nrel;
Nick Cliftonffcb7af2000-09-15 18:07:28 +00003222
Richard Hendersond1c109d2014-04-21 08:14:18 -07003223 insn = bfd_get_32 (abfd, contents + urel_r_offset);
Richard Henderson252b5131999-05-03 07:29:11 +00003224
3225 switch (urel->r_addend)
3226 {
Richard Henderson9e756d62002-06-02 02:28:45 +00003227 case LITUSE_ALPHA_ADDR:
3228 default:
Richard Henderson252b5131999-05-03 07:29:11 +00003229 /* This type is really just a placeholder to note that all
3230 uses cannot be optimized, but to still allow some. */
Alan Modra0a1b45a2021-03-31 10:30:54 +10303231 all_optimized = false;
Richard Henderson252b5131999-05-03 07:29:11 +00003232 break;
3233
Richard Henderson9e756d62002-06-02 02:28:45 +00003234 case LITUSE_ALPHA_BASE:
Richard Hendersond1c109d2014-04-21 08:14:18 -07003235 /* We may only create GPREL relocs during the second pass. */
3236 if (relax_pass == 0)
3237 {
Alan Modra0a1b45a2021-03-31 10:30:54 +10303238 all_optimized = false;
Richard Hendersond1c109d2014-04-21 08:14:18 -07003239 break;
3240 }
3241
Richard Henderson252b5131999-05-03 07:29:11 +00003242 /* We can always optimize 16-bit displacements. */
Nick Cliftonffcb7af2000-09-15 18:07:28 +00003243
3244 /* Extract the displacement from the instruction, sign-extending
3245 it if necessary, then test whether it is within 16 or 32 bits
3246 displacement from GP. */
Richard Hendersond6ad34f2005-05-22 22:13:21 +00003247 insn_disp = ((insn & 0xffff) ^ 0x8000) - 0x8000;
Nick Cliftonffcb7af2000-09-15 18:07:28 +00003248
3249 xdisp = disp + insn_disp;
Richard Henderson9e756d62002-06-02 02:28:45 +00003250 fits16 = (xdisp >= - (bfd_signed_vma) 0x8000 && xdisp < 0x8000);
3251 fits32 = (xdisp >= - (bfd_signed_vma) 0x80000000
3252 && xdisp < 0x7fff8000);
Nick Cliftonffcb7af2000-09-15 18:07:28 +00003253
Richard Henderson252b5131999-05-03 07:29:11 +00003254 if (fits16)
3255 {
Nick Cliftonffcb7af2000-09-15 18:07:28 +00003256 /* Take the op code and dest from this insn, take the base
Kazu Hiratafe8bc632000-12-09 01:54:51 +00003257 register from the literal insn. Leave the offset alone. */
Nick Cliftonffcb7af2000-09-15 18:07:28 +00003258 insn = (insn & 0xffe0ffff) | (lit_insn & 0x001f0000);
Richard Hendersond1c109d2014-04-21 08:14:18 -07003259 bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset);
Alan Modra0a1b45a2021-03-31 10:30:54 +10303260 changed_contents = true;
Richard Henderson252b5131999-05-03 07:29:11 +00003261
Richard Hendersond1c109d2014-04-21 08:14:18 -07003262 nrel = *urel;
3263 nrel.r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
3264 R_ALPHA_GPREL16);
3265 nrel.r_addend = irel->r_addend;
3266
3267 /* As we adjust, move the reloc to the end so that we don't
Alan Modra07d6d2b2017-12-06 09:26:00 +10303268 break the LITERAL+LITUSE chain. */
Richard Hendersond1c109d2014-04-21 08:14:18 -07003269 if (urel < --erel)
Alan Modra07d6d2b2017-12-06 09:26:00 +10303270 *urel-- = *erel;
Richard Hendersond1c109d2014-04-21 08:14:18 -07003271 *erel = nrel;
Alan Modra0a1b45a2021-03-31 10:30:54 +10303272 changed_relocs = true;
Richard Henderson252b5131999-05-03 07:29:11 +00003273 }
3274
3275 /* If all mem+byte, we can optimize 32-bit mem displacements. */
3276 else if (fits32 && !(flags & ~6))
3277 {
Nick Cliftonffcb7af2000-09-15 18:07:28 +00003278 /* FIXME: sanity check that lit insn Ra is mem insn Rb. */
Richard Henderson252b5131999-05-03 07:29:11 +00003279
3280 irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
3281 R_ALPHA_GPRELHIGH);
3282 lit_insn = (OP_LDAH << 26) | (lit_insn & 0x03ff0000);
Richard Hendersond1c109d2014-04-21 08:14:18 -07003283 bfd_put_32 (abfd, (bfd_vma) lit_insn, contents + irel->r_offset);
Alan Modra0a1b45a2021-03-31 10:30:54 +10303284 lit_reused = true;
3285 changed_contents = true;
Richard Henderson252b5131999-05-03 07:29:11 +00003286
Alan Modra07d6d2b2017-12-06 09:26:00 +10303287 /* Since all relocs must be optimized, don't bother swapping
3288 this relocation to the end. */
Richard Henderson252b5131999-05-03 07:29:11 +00003289 urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
3290 R_ALPHA_GPRELLOW);
3291 urel->r_addend = irel->r_addend;
Alan Modra0a1b45a2021-03-31 10:30:54 +10303292 changed_relocs = true;
Richard Henderson252b5131999-05-03 07:29:11 +00003293 }
3294 else
Alan Modra0a1b45a2021-03-31 10:30:54 +10303295 all_optimized = false;
Richard Henderson252b5131999-05-03 07:29:11 +00003296 break;
3297
Richard Henderson9e756d62002-06-02 02:28:45 +00003298 case LITUSE_ALPHA_BYTOFF:
Richard Henderson252b5131999-05-03 07:29:11 +00003299 /* We can always optimize byte instructions. */
3300
3301 /* FIXME: sanity check the insn for byte op. Check that the
3302 literal dest reg is indeed Rb in the byte insn. */
3303
Alan Modradc810e32001-09-18 09:57:26 +00003304 insn &= ~ (unsigned) 0x001ff000;
3305 insn |= ((symval & 7) << 13) | 0x1000;
Richard Hendersond1c109d2014-04-21 08:14:18 -07003306 bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset);
Alan Modra0a1b45a2021-03-31 10:30:54 +10303307 changed_contents = true;
Richard Henderson252b5131999-05-03 07:29:11 +00003308
Richard Hendersond1c109d2014-04-21 08:14:18 -07003309 nrel = *urel;
3310 nrel.r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
3311 nrel.r_addend = 0;
Richard Henderson252b5131999-05-03 07:29:11 +00003312
Richard Hendersond1c109d2014-04-21 08:14:18 -07003313 /* As we adjust, move the reloc to the end so that we don't
3314 break the LITERAL+LITUSE chain. */
3315 if (urel < --erel)
3316 *urel-- = *erel;
3317 *erel = nrel;
Alan Modra0a1b45a2021-03-31 10:30:54 +10303318 changed_relocs = true;
Richard Henderson252b5131999-05-03 07:29:11 +00003319 break;
3320
Richard Henderson9e756d62002-06-02 02:28:45 +00003321 case LITUSE_ALPHA_JSR:
3322 case LITUSE_ALPHA_TLSGD:
3323 case LITUSE_ALPHA_TLSLDM:
Richard Henderson8288a392005-05-31 22:53:44 +00003324 case LITUSE_ALPHA_JSRDIRECT:
Richard Henderson252b5131999-05-03 07:29:11 +00003325 {
Richard Hendersonf44f99a2002-06-02 03:58:40 +00003326 bfd_vma optdest, org;
Richard Henderson252b5131999-05-03 07:29:11 +00003327 bfd_signed_vma odisp;
3328
Richard Hendersond6ad34f2005-05-22 22:13:21 +00003329 /* For undefined weak symbols, we're mostly interested in getting
3330 rid of the got entry whenever possible, so optimize this to a
3331 use of the zero register. */
3332 if (info->h && info->h->root.root.type == bfd_link_hash_undefweak)
3333 {
3334 insn |= 31 << 16;
Richard Hendersond1c109d2014-04-21 08:14:18 -07003335 bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset);
Richard Hendersond6ad34f2005-05-22 22:13:21 +00003336
Alan Modra0a1b45a2021-03-31 10:30:54 +10303337 changed_contents = true;
Richard Hendersond6ad34f2005-05-22 22:13:21 +00003338 break;
3339 }
3340
Richard Hendersonf44f99a2002-06-02 03:58:40 +00003341 /* If not zero, place to jump without needing pv. */
3342 optdest = elf64_alpha_relax_opt_call (info, symval);
Richard Hendersond1c109d2014-04-21 08:14:18 -07003343 org = sec_output_vma + urel_r_offset + 4;
Richard Henderson252b5131999-05-03 07:29:11 +00003344 odisp = (optdest ? optdest : symval) - org;
Richard Hendersonf44f99a2002-06-02 03:58:40 +00003345
Richard Henderson252b5131999-05-03 07:29:11 +00003346 if (odisp >= -0x400000 && odisp < 0x400000)
3347 {
3348 Elf_Internal_Rela *xrel;
3349
Kazu Hiratafe8bc632000-12-09 01:54:51 +00003350 /* Preserve branch prediction call stack when possible. */
Richard Henderson252b5131999-05-03 07:29:11 +00003351 if ((insn & INSN_JSR_MASK) == INSN_JSR)
3352 insn = (OP_BSR << 26) | (insn & 0x03e00000);
3353 else
3354 insn = (OP_BR << 26) | (insn & 0x03e00000);
Richard Hendersond1c109d2014-04-21 08:14:18 -07003355 bfd_put_32 (abfd, (bfd_vma) insn, contents + urel_r_offset);
Alan Modra0a1b45a2021-03-31 10:30:54 +10303356 changed_contents = true;
Kazu Hiratafe8bc632000-12-09 01:54:51 +00003357
Richard Hendersond1c109d2014-04-21 08:14:18 -07003358 nrel = *urel;
3359 nrel.r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
3360 R_ALPHA_BRADDR);
3361 nrel.r_addend = irel->r_addend;
Richard Henderson252b5131999-05-03 07:29:11 +00003362
3363 if (optdest)
Richard Hendersond1c109d2014-04-21 08:14:18 -07003364 nrel.r_addend += optdest - symval;
Richard Henderson252b5131999-05-03 07:29:11 +00003365 else
Alan Modra0a1b45a2021-03-31 10:30:54 +10303366 all_optimized = false;
Richard Henderson252b5131999-05-03 07:29:11 +00003367
Richard Henderson252b5131999-05-03 07:29:11 +00003368 /* Kill any HINT reloc that might exist for this insn. */
3369 xrel = (elf64_alpha_find_reloc_at_ofs
Richard Hendersond1c109d2014-04-21 08:14:18 -07003370 (info->relocs, info->relend, urel_r_offset,
Richard Henderson252b5131999-05-03 07:29:11 +00003371 R_ALPHA_HINT));
3372 if (xrel)
3373 xrel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
3374
Richard Hendersond1c109d2014-04-21 08:14:18 -07003375 /* As we adjust, move the reloc to the end so that we don't
3376 break the LITERAL+LITUSE chain. */
3377 if (urel < --erel)
3378 *urel-- = *erel;
3379 *erel = nrel;
3380
Alan Modra0a1b45a2021-03-31 10:30:54 +10303381 info->changed_relocs = true;
Richard Henderson252b5131999-05-03 07:29:11 +00003382 }
3383 else
Alan Modra0a1b45a2021-03-31 10:30:54 +10303384 all_optimized = false;
Richard Henderson252b5131999-05-03 07:29:11 +00003385
Richard Henderson1cd68952001-09-09 20:42:11 +00003386 /* Even if the target is not in range for a direct branch,
3387 if we share a GP, we can eliminate the gp reload. */
3388 if (optdest)
3389 {
3390 Elf_Internal_Rela *gpdisp
3391 = (elf64_alpha_find_reloc_at_ofs
Richard Hendersond1c109d2014-04-21 08:14:18 -07003392 (info->relocs, irelend, urel_r_offset + 4,
Richard Henderson9e756d62002-06-02 02:28:45 +00003393 R_ALPHA_GPDISP));
Richard Henderson1cd68952001-09-09 20:42:11 +00003394 if (gpdisp)
3395 {
Richard Hendersond1c109d2014-04-21 08:14:18 -07003396 bfd_byte *p_ldah = contents + gpdisp->r_offset;
Richard Henderson1cd68952001-09-09 20:42:11 +00003397 bfd_byte *p_lda = p_ldah + gpdisp->r_addend;
Richard Hendersond1c109d2014-04-21 08:14:18 -07003398 unsigned int ldah = bfd_get_32 (abfd, p_ldah);
3399 unsigned int lda = bfd_get_32 (abfd, p_lda);
Richard Henderson252b5131999-05-03 07:29:11 +00003400
Richard Henderson1cd68952001-09-09 20:42:11 +00003401 /* Verify that the instruction is "ldah $29,0($26)".
3402 Consider a function that ends in a noreturn call,
3403 and that the next function begins with an ldgp,
3404 and that by accident there is no padding between.
3405 In that case the insn would use $27 as the base. */
3406 if (ldah == 0x27ba0000 && lda == 0x23bd0000)
3407 {
Richard Hendersond1c109d2014-04-21 08:14:18 -07003408 bfd_put_32 (abfd, (bfd_vma) INSN_UNOP, p_ldah);
3409 bfd_put_32 (abfd, (bfd_vma) INSN_UNOP, p_lda);
Richard Henderson1cd68952001-09-09 20:42:11 +00003410
3411 gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
Alan Modra0a1b45a2021-03-31 10:30:54 +10303412 changed_contents = true;
3413 changed_relocs = true;
Richard Henderson1cd68952001-09-09 20:42:11 +00003414 }
3415 }
3416 }
Richard Henderson252b5131999-05-03 07:29:11 +00003417 }
3418 break;
3419 }
3420 }
3421
Richard Hendersond1c109d2014-04-21 08:14:18 -07003422 /* If we reused the literal instruction, we must have optimized all. */
3423 BFD_ASSERT(!lit_reused || all_optimized);
3424
Richard Henderson252b5131999-05-03 07:29:11 +00003425 /* If all cases were optimized, we can reduce the use count on this
3426 got entry by one, possibly eliminating it. */
3427 if (all_optimized)
3428 {
Richard Henderson3765b1b2002-05-30 22:01:38 +00003429 if (--info->gotent->use_count == 0)
3430 {
Richard Henderson9e756d62002-06-02 02:28:45 +00003431 int sz = alpha_got_entry_size (R_ALPHA_LITERAL);
3432 alpha_elf_tdata (info->gotobj)->total_got_size -= sz;
Richard Henderson3765b1b2002-05-30 22:01:38 +00003433 if (!info->h)
Richard Henderson9e756d62002-06-02 02:28:45 +00003434 alpha_elf_tdata (info->gotobj)->local_got_size -= sz;
Richard Henderson3765b1b2002-05-30 22:01:38 +00003435 }
Richard Henderson252b5131999-05-03 07:29:11 +00003436
3437 /* If the literal instruction is no longer needed (it may have been
Richard Henderson3765b1b2002-05-30 22:01:38 +00003438 reused. We can eliminate it. */
3439 /* ??? For now, I don't want to deal with compacting the section,
Richard Henderson252b5131999-05-03 07:29:11 +00003440 so just nop it out. */
3441 if (!lit_reused)
3442 {
3443 irel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
Alan Modra0a1b45a2021-03-31 10:30:54 +10303444 changed_relocs = true;
Richard Henderson252b5131999-05-03 07:29:11 +00003445
Richard Hendersond1c109d2014-04-21 08:14:18 -07003446 bfd_put_32 (abfd, (bfd_vma) INSN_UNOP, contents + irel->r_offset);
Alan Modra0a1b45a2021-03-31 10:30:54 +10303447 changed_contents = true;
Richard Henderson252b5131999-05-03 07:29:11 +00003448 }
Richard Hendersond6ad34f2005-05-22 22:13:21 +00003449 }
Richard Hendersond1c109d2014-04-21 08:14:18 -07003450
3451 info->changed_contents = changed_contents;
3452 info->changed_relocs = changed_relocs;
3453
3454 if (all_optimized || relax_pass == 0)
Alan Modra0a1b45a2021-03-31 10:30:54 +10303455 return true;
Richard Hendersond1c109d2014-04-21 08:14:18 -07003456 return elf64_alpha_relax_got_load (info, symval, irel, R_ALPHA_LITERAL);
Richard Henderson252b5131999-05-03 07:29:11 +00003457}
3458
Alan Modra0a1b45a2021-03-31 10:30:54 +10303459static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00003460elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval,
Alan Modra0a1b45a2021-03-31 10:30:54 +10303461 Elf_Internal_Rela *irel, bool is_gd)
Richard Henderson9e756d62002-06-02 02:28:45 +00003462{
3463 bfd_byte *pos[5];
Richard Henderson891caa92010-08-09 23:58:52 +00003464 unsigned int insn, tlsgd_reg;
Richard Henderson9e756d62002-06-02 02:28:45 +00003465 Elf_Internal_Rela *gpdisp, *hint;
Alan Modra0a1b45a2021-03-31 10:30:54 +10303466 bool dynamic, use_gottprel;
Richard Hendersoncc03ec82003-01-22 00:47:58 +00003467 unsigned long new_symndx;
Richard Henderson9e756d62002-06-02 02:28:45 +00003468
Alan Modrac415c832020-08-27 21:54:16 +09303469 dynamic = (info->h != NULL
3470 && alpha_elf_dynamic_symbol_p (&info->h->root, info->link_info));
Richard Henderson9e756d62002-06-02 02:28:45 +00003471
Richard Henderson9e756d62002-06-02 02:28:45 +00003472 /* If a TLS symbol is accessed using IE at least once, there is no point
3473 to use dynamic model for it. */
3474 if (is_gd && info->h && (info->h->flags & ALPHA_ELF_LINK_HASH_TLS_IE))
3475 ;
3476
3477 /* If the symbol is local, and we've already committed to DF_STATIC_TLS,
3478 then we might as well relax to IE. */
H.J. Lu0e1862b2015-08-18 05:51:03 -07003479 else if (bfd_link_pic (info->link_info) && !dynamic
Richard Henderson9e756d62002-06-02 02:28:45 +00003480 && (info->link_info->flags & DF_STATIC_TLS))
3481 ;
3482
3483 /* Otherwise we must be building an executable to do anything. */
H.J. Lu0e1862b2015-08-18 05:51:03 -07003484 else if (bfd_link_pic (info->link_info))
Alan Modra0a1b45a2021-03-31 10:30:54 +10303485 return true;
Richard Henderson9e756d62002-06-02 02:28:45 +00003486
3487 /* The TLSGD/TLSLDM relocation must be followed by a LITERAL and
3488 the matching LITUSE_TLS relocations. */
3489 if (irel + 2 >= info->relend)
Alan Modra0a1b45a2021-03-31 10:30:54 +10303490 return true;
Richard Henderson9e756d62002-06-02 02:28:45 +00003491 if (ELF64_R_TYPE (irel[1].r_info) != R_ALPHA_LITERAL
3492 || ELF64_R_TYPE (irel[2].r_info) != R_ALPHA_LITUSE
3493 || irel[2].r_addend != (is_gd ? LITUSE_ALPHA_TLSGD : LITUSE_ALPHA_TLSLDM))
Alan Modra0a1b45a2021-03-31 10:30:54 +10303494 return true;
Richard Henderson9e756d62002-06-02 02:28:45 +00003495
3496 /* There must be a GPDISP relocation positioned immediately after the
3497 LITUSE relocation. */
3498 gpdisp = elf64_alpha_find_reloc_at_ofs (info->relocs, info->relend,
3499 irel[2].r_offset + 4, R_ALPHA_GPDISP);
3500 if (!gpdisp)
Alan Modra0a1b45a2021-03-31 10:30:54 +10303501 return true;
Richard Henderson9e756d62002-06-02 02:28:45 +00003502
3503 pos[0] = info->contents + irel[0].r_offset;
3504 pos[1] = info->contents + irel[1].r_offset;
3505 pos[2] = info->contents + irel[2].r_offset;
3506 pos[3] = info->contents + gpdisp->r_offset;
3507 pos[4] = pos[3] + gpdisp->r_addend;
3508
Richard Henderson7dbf3b72011-06-24 17:38:17 +00003509 /* Beware of the compiler hoisting part of the sequence out a loop
3510 and adjusting the destination register for the TLSGD insn. If this
3511 happens, there will be a move into $16 before the JSR insn, so only
3512 transformations of the first insn pair should use this register. */
3513 tlsgd_reg = bfd_get_32 (info->abfd, pos[0]);
3514 tlsgd_reg = (tlsgd_reg >> 21) & 31;
3515
Richard Henderson1bbc9ce2003-01-21 08:59:25 +00003516 /* Generally, the positions are not allowed to be out of order, lest the
3517 modified insn sequence have different register lifetimes. We can make
3518 an exception when pos 1 is adjacent to pos 0. */
3519 if (pos[1] + 4 == pos[0])
Richard Henderson9e756d62002-06-02 02:28:45 +00003520 {
3521 bfd_byte *tmp = pos[0];
3522 pos[0] = pos[1];
3523 pos[1] = tmp;
3524 }
Richard Henderson1bbc9ce2003-01-21 08:59:25 +00003525 if (pos[1] >= pos[2] || pos[2] >= pos[3])
Alan Modra0a1b45a2021-03-31 10:30:54 +10303526 return true;
Richard Henderson9e756d62002-06-02 02:28:45 +00003527
3528 /* Reduce the use count on the LITERAL relocation. Do this before we
3529 smash the symndx when we adjust the relocations below. */
3530 {
3531 struct alpha_elf_got_entry *lit_gotent;
3532 struct alpha_elf_link_hash_entry *lit_h;
3533 unsigned long indx;
3534
3535 BFD_ASSERT (ELF64_R_SYM (irel[1].r_info) >= info->symtab_hdr->sh_info);
3536 indx = ELF64_R_SYM (irel[1].r_info) - info->symtab_hdr->sh_info;
3537 lit_h = alpha_elf_sym_hashes (info->abfd)[indx];
3538
3539 while (lit_h->root.root.type == bfd_link_hash_indirect
3540 || lit_h->root.root.type == bfd_link_hash_warning)
3541 lit_h = (struct alpha_elf_link_hash_entry *) lit_h->root.root.u.i.link;
3542
3543 for (lit_gotent = lit_h->got_entries; lit_gotent ;
3544 lit_gotent = lit_gotent->next)
3545 if (lit_gotent->gotobj == info->gotobj
3546 && lit_gotent->reloc_type == R_ALPHA_LITERAL
3547 && lit_gotent->addend == irel[1].r_addend)
3548 break;
3549 BFD_ASSERT (lit_gotent);
3550
3551 if (--lit_gotent->use_count == 0)
3552 {
3553 int sz = alpha_got_entry_size (R_ALPHA_LITERAL);
3554 alpha_elf_tdata (info->gotobj)->total_got_size -= sz;
3555 }
3556 }
3557
3558 /* Change
3559
Richard Hendersona7519a32005-05-26 07:14:03 +00003560 lda $16,x($gp) !tlsgd!1
3561 ldq $27,__tls_get_addr($gp) !literal!1
3562 jsr $26,($27),__tls_get_addr !lituse_tlsgd!1
3563 ldah $29,0($26) !gpdisp!2
3564 lda $29,0($29) !gpdisp!2
Richard Henderson9e756d62002-06-02 02:28:45 +00003565 to
Richard Hendersona7519a32005-05-26 07:14:03 +00003566 ldq $16,x($gp) !gottprel
Richard Henderson9e756d62002-06-02 02:28:45 +00003567 unop
3568 call_pal rduniq
3569 addq $16,$0,$0
3570 unop
3571 or the first pair to
Richard Hendersona7519a32005-05-26 07:14:03 +00003572 lda $16,x($gp) !tprel
Richard Henderson9e756d62002-06-02 02:28:45 +00003573 unop
3574 or
Richard Hendersona7519a32005-05-26 07:14:03 +00003575 ldah $16,x($gp) !tprelhi
3576 lda $16,x($16) !tprello
Richard Henderson9e756d62002-06-02 02:28:45 +00003577
3578 as appropriate. */
3579
Alan Modra0a1b45a2021-03-31 10:30:54 +10303580 use_gottprel = false;
Thomas Schwingecf356382010-09-24 12:14:26 +00003581 new_symndx = is_gd ? ELF64_R_SYM (irel->r_info) : STN_UNDEF;
Richard Henderson891caa92010-08-09 23:58:52 +00003582
Roland McGrath9a757e42013-10-09 19:40:04 +00003583 /* Some compilers warn about a Boolean-looking expression being
3584 used in a switch. The explicit cast silences them. */
H.J. Lu0e1862b2015-08-18 05:51:03 -07003585 switch ((int) (!dynamic && !bfd_link_pic (info->link_info)))
Richard Henderson9e756d62002-06-02 02:28:45 +00003586 {
3587 case 1:
3588 {
3589 bfd_vma tp_base;
3590 bfd_signed_vma disp;
3591
Alan Modrae1918d22003-11-04 06:16:39 +00003592 BFD_ASSERT (elf_hash_table (info->link_info)->tls_sec != NULL);
3593 tp_base = alpha_get_tprel_base (info->link_info);
Richard Henderson9e756d62002-06-02 02:28:45 +00003594 disp = symval - tp_base;
3595
3596 if (disp >= -0x8000 && disp < 0x8000)
3597 {
Richard Henderson891caa92010-08-09 23:58:52 +00003598 insn = (OP_LDA << 26) | (tlsgd_reg << 21) | (31 << 16);
Richard Henderson9e756d62002-06-02 02:28:45 +00003599 bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]);
3600 bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]);
3601
3602 irel[0].r_offset = pos[0] - info->contents;
Richard Hendersoncc03ec82003-01-22 00:47:58 +00003603 irel[0].r_info = ELF64_R_INFO (new_symndx, R_ALPHA_TPREL16);
Richard Henderson9e756d62002-06-02 02:28:45 +00003604 irel[1].r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
3605 break;
3606 }
3607 else if (disp >= -(bfd_signed_vma) 0x80000000
Richard Henderson1bbc9ce2003-01-21 08:59:25 +00003608 && disp < (bfd_signed_vma) 0x7fff8000
Richard Henderson891caa92010-08-09 23:58:52 +00003609 && pos[0] + 4 == pos[1])
Richard Henderson9e756d62002-06-02 02:28:45 +00003610 {
Richard Henderson891caa92010-08-09 23:58:52 +00003611 insn = (OP_LDAH << 26) | (tlsgd_reg << 21) | (31 << 16);
Richard Henderson9e756d62002-06-02 02:28:45 +00003612 bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]);
Richard Henderson891caa92010-08-09 23:58:52 +00003613 insn = (OP_LDA << 26) | (tlsgd_reg << 21) | (tlsgd_reg << 16);
Richard Henderson9e756d62002-06-02 02:28:45 +00003614 bfd_put_32 (info->abfd, (bfd_vma) insn, pos[1]);
3615
3616 irel[0].r_offset = pos[0] - info->contents;
Richard Hendersoncc03ec82003-01-22 00:47:58 +00003617 irel[0].r_info = ELF64_R_INFO (new_symndx, R_ALPHA_TPRELHI);
Richard Henderson9e756d62002-06-02 02:28:45 +00003618 irel[1].r_offset = pos[1] - info->contents;
Richard Hendersoncc03ec82003-01-22 00:47:58 +00003619 irel[1].r_info = ELF64_R_INFO (new_symndx, R_ALPHA_TPRELLO);
Richard Henderson9e756d62002-06-02 02:28:45 +00003620 break;
3621 }
3622 }
3623 /* FALLTHRU */
3624
3625 default:
Alan Modra0a1b45a2021-03-31 10:30:54 +10303626 use_gottprel = true;
Richard Henderson9e756d62002-06-02 02:28:45 +00003627
Richard Henderson891caa92010-08-09 23:58:52 +00003628 insn = (OP_LDQ << 26) | (tlsgd_reg << 21) | (29 << 16);
Richard Henderson9e756d62002-06-02 02:28:45 +00003629 bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]);
3630 bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]);
3631
3632 irel[0].r_offset = pos[0] - info->contents;
Richard Hendersoncc03ec82003-01-22 00:47:58 +00003633 irel[0].r_info = ELF64_R_INFO (new_symndx, R_ALPHA_GOTTPREL);
Richard Henderson9e756d62002-06-02 02:28:45 +00003634 irel[1].r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
3635 break;
3636 }
3637
3638 bfd_put_32 (info->abfd, (bfd_vma) INSN_RDUNIQ, pos[2]);
3639
3640 insn = INSN_ADDQ | (16 << 21) | (0 << 16) | (0 << 0);
3641 bfd_put_32 (info->abfd, (bfd_vma) insn, pos[3]);
3642
3643 bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[4]);
3644
3645 irel[2].r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
3646 gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
3647
3648 hint = elf64_alpha_find_reloc_at_ofs (info->relocs, info->relend,
3649 irel[2].r_offset, R_ALPHA_HINT);
3650 if (hint)
3651 hint->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
3652
Alan Modra0a1b45a2021-03-31 10:30:54 +10303653 info->changed_contents = true;
3654 info->changed_relocs = true;
Richard Henderson9e756d62002-06-02 02:28:45 +00003655
3656 /* Reduce the use count on the TLSGD/TLSLDM relocation. */
3657 if (--info->gotent->use_count == 0)
3658 {
3659 int sz = alpha_got_entry_size (info->gotent->reloc_type);
3660 alpha_elf_tdata (info->gotobj)->total_got_size -= sz;
3661 if (!info->h)
3662 alpha_elf_tdata (info->gotobj)->local_got_size -= sz;
3663 }
3664
3665 /* If we've switched to a GOTTPREL relocation, increment the reference
3666 count on that got entry. */
3667 if (use_gottprel)
3668 {
3669 struct alpha_elf_got_entry *tprel_gotent;
3670
3671 for (tprel_gotent = *info->first_gotent; tprel_gotent ;
3672 tprel_gotent = tprel_gotent->next)
3673 if (tprel_gotent->gotobj == info->gotobj
3674 && tprel_gotent->reloc_type == R_ALPHA_GOTTPREL
3675 && tprel_gotent->addend == irel->r_addend)
3676 break;
3677 if (tprel_gotent)
3678 tprel_gotent->use_count++;
3679 else
3680 {
3681 if (info->gotent->use_count == 0)
3682 tprel_gotent = info->gotent;
3683 else
3684 {
3685 tprel_gotent = (struct alpha_elf_got_entry *)
3686 bfd_alloc (info->abfd, sizeof (struct alpha_elf_got_entry));
3687 if (!tprel_gotent)
Alan Modra0a1b45a2021-03-31 10:30:54 +10303688 return false;
Richard Henderson9e756d62002-06-02 02:28:45 +00003689
3690 tprel_gotent->next = *info->first_gotent;
3691 *info->first_gotent = tprel_gotent;
3692
3693 tprel_gotent->gotobj = info->gotobj;
3694 tprel_gotent->addend = irel->r_addend;
3695 tprel_gotent->got_offset = -1;
3696 tprel_gotent->reloc_done = 0;
3697 tprel_gotent->reloc_xlated = 0;
3698 }
3699
3700 tprel_gotent->use_count = 1;
3701 tprel_gotent->reloc_type = R_ALPHA_GOTTPREL;
3702 }
3703 }
3704
Alan Modra0a1b45a2021-03-31 10:30:54 +10303705 return true;
Richard Henderson9e756d62002-06-02 02:28:45 +00003706}
3707
Alan Modra0a1b45a2021-03-31 10:30:54 +10303708static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00003709elf64_alpha_relax_section (bfd *abfd, asection *sec,
Alan Modra0a1b45a2021-03-31 10:30:54 +10303710 struct bfd_link_info *link_info, bool *again)
Richard Henderson252b5131999-05-03 07:29:11 +00003711{
3712 Elf_Internal_Shdr *symtab_hdr;
3713 Elf_Internal_Rela *internal_relocs;
Richard Henderson252b5131999-05-03 07:29:11 +00003714 Elf_Internal_Rela *irel, *irelend;
Alan Modra6cdc0cc2002-07-07 09:10:41 +00003715 Elf_Internal_Sym *isymbuf = NULL;
Richard Henderson252b5131999-05-03 07:29:11 +00003716 struct alpha_elf_got_entry **local_got_entries;
3717 struct alpha_relax_info info;
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00003718 struct alpha_elf_link_hash_table * htab;
Richard Hendersond1c109d2014-04-21 08:14:18 -07003719 int relax_pass;
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00003720
3721 htab = alpha_elf_hash_table (link_info);
3722 if (htab == NULL)
Alan Modra0a1b45a2021-03-31 10:30:54 +10303723 return false;
Richard Henderson252b5131999-05-03 07:29:11 +00003724
Richard Henderson4a828aa2007-04-10 18:00:26 +00003725 /* There's nothing to change, yet. */
Alan Modra0a1b45a2021-03-31 10:30:54 +10303726 *again = false;
Richard Henderson252b5131999-05-03 07:29:11 +00003727
H.J. Lu0e1862b2015-08-18 05:51:03 -07003728 if (bfd_link_relocatable (link_info)
Richard Henderson32412782005-05-23 01:26:58 +00003729 || ((sec->flags & (SEC_CODE | SEC_RELOC | SEC_ALLOC))
3730 != (SEC_CODE | SEC_RELOC | SEC_ALLOC))
Richard Henderson252b5131999-05-03 07:29:11 +00003731 || sec->reloc_count == 0)
Alan Modra0a1b45a2021-03-31 10:30:54 +10303732 return true;
Richard Henderson252b5131999-05-03 07:29:11 +00003733
Nick Clifton0ffa91d2008-02-12 11:32:31 +00003734 BFD_ASSERT (is_alpha_elf (abfd));
Richard Hendersond1c109d2014-04-21 08:14:18 -07003735 relax_pass = link_info->relax_pass;
Nick Clifton0ffa91d2008-02-12 11:32:31 +00003736
Richard Henderson4a828aa2007-04-10 18:00:26 +00003737 /* Make sure our GOT and PLT tables are up-to-date. */
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00003738 if (htab->relax_trip != link_info->relax_trip)
Richard Henderson4a828aa2007-04-10 18:00:26 +00003739 {
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00003740 htab->relax_trip = link_info->relax_trip;
Richard Henderson4a828aa2007-04-10 18:00:26 +00003741
Richard Hendersond1c109d2014-04-21 08:14:18 -07003742 /* This should never fail after the initial round, since the only error
Alan Modra07d6d2b2017-12-06 09:26:00 +10303743 is GOT overflow, and relaxation only shrinks the table. However, we
Richard Hendersond1c109d2014-04-21 08:14:18 -07003744 may only merge got sections during the first pass. If we merge
3745 sections after we've created GPREL relocs, the GP for the merged
3746 section backs up which may put the relocs out of range. */
3747 if (!elf64_alpha_size_got_sections (link_info, relax_pass == 0))
Richard Henderson4a828aa2007-04-10 18:00:26 +00003748 abort ();
3749 if (elf_hash_table (link_info)->dynamic_sections_created)
3750 {
3751 elf64_alpha_size_plt_section (link_info);
3752 elf64_alpha_size_rela_got_section (link_info);
3753 }
3754 }
3755
Nick Clifton0ffa91d2008-02-12 11:32:31 +00003756 symtab_hdr = &elf_symtab_hdr (abfd);
Richard Henderson252b5131999-05-03 07:29:11 +00003757 local_got_entries = alpha_elf_tdata(abfd)->local_got_entries;
3758
3759 /* Load the relocations for this section. */
Alan Modra45d6a902003-05-09 02:27:11 +00003760 internal_relocs = (_bfd_elf_link_read_relocs
Nick Clifton2c3fc382012-07-13 14:22:50 +00003761 (abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
Richard Henderson252b5131999-05-03 07:29:11 +00003762 link_info->keep_memory));
3763 if (internal_relocs == NULL)
Alan Modra0a1b45a2021-03-31 10:30:54 +10303764 return false;
Richard Henderson252b5131999-05-03 07:29:11 +00003765
Kazu Hiratafe8bc632000-12-09 01:54:51 +00003766 memset(&info, 0, sizeof (info));
Richard Henderson252b5131999-05-03 07:29:11 +00003767 info.abfd = abfd;
3768 info.sec = sec;
3769 info.link_info = link_info;
Richard Henderson9e756d62002-06-02 02:28:45 +00003770 info.symtab_hdr = symtab_hdr;
Richard Henderson252b5131999-05-03 07:29:11 +00003771 info.relocs = internal_relocs;
3772 info.relend = irelend = internal_relocs + sec->reloc_count;
3773
Kazu Hiratacedb70c2002-06-03 01:57:10 +00003774 /* Find the GP for this object. Do not store the result back via
Richard Hendersonb6462612002-06-01 21:56:41 +00003775 _bfd_set_gp_value, since this could change again before final. */
Richard Henderson252b5131999-05-03 07:29:11 +00003776 info.gotobj = alpha_elf_tdata (abfd)->gotobj;
3777 if (info.gotobj)
3778 {
3779 asection *sgot = alpha_elf_tdata (info.gotobj)->got;
Richard Hendersonb6462612002-06-01 21:56:41 +00003780 info.gp = (sgot->output_section->vma
3781 + sgot->output_offset
3782 + 0x8000);
Richard Henderson252b5131999-05-03 07:29:11 +00003783 }
3784
Richard Henderson9e756d62002-06-02 02:28:45 +00003785 /* Get the section contents. */
3786 if (elf_section_data (sec)->this_hdr.contents != NULL)
3787 info.contents = elf_section_data (sec)->this_hdr.contents;
3788 else
3789 {
Alan Modraeea61212004-06-24 04:46:28 +00003790 if (!bfd_malloc_and_get_section (abfd, sec, &info.contents))
Richard Henderson9e756d62002-06-02 02:28:45 +00003791 goto error_return;
3792 }
3793
Richard Henderson252b5131999-05-03 07:29:11 +00003794 for (irel = internal_relocs; irel < irelend; irel++)
3795 {
3796 bfd_vma symval;
Richard Henderson252b5131999-05-03 07:29:11 +00003797 struct alpha_elf_got_entry *gotent;
Richard Henderson9e756d62002-06-02 02:28:45 +00003798 unsigned long r_type = ELF64_R_TYPE (irel->r_info);
Richard Hendersoncc03ec82003-01-22 00:47:58 +00003799 unsigned long r_symndx = ELF64_R_SYM (irel->r_info);
Richard Henderson252b5131999-05-03 07:29:11 +00003800
Richard Henderson9e756d62002-06-02 02:28:45 +00003801 /* Early exit for unhandled or unrelaxable relocations. */
Richard Hendersond1c109d2014-04-21 08:14:18 -07003802 if (r_type != R_ALPHA_LITERAL)
Alan Modra07d6d2b2017-12-06 09:26:00 +10303803 {
3804 /* We complete everything except LITERAL in the first pass. */
Richard Hendersond1c109d2014-04-21 08:14:18 -07003805 if (relax_pass != 0)
3806 continue;
3807 if (r_type == R_ALPHA_TLSLDM)
3808 {
3809 /* The symbol for a TLSLDM reloc is ignored. Collapse the
Alan Modra07d6d2b2017-12-06 09:26:00 +10303810 reloc to the STN_UNDEF (0) symbol so that they all match. */
Richard Hendersond1c109d2014-04-21 08:14:18 -07003811 r_symndx = STN_UNDEF;
3812 }
3813 else if (r_type != R_ALPHA_GOTDTPREL
Alan Modra07d6d2b2017-12-06 09:26:00 +10303814 && r_type != R_ALPHA_GOTTPREL
Richard Hendersond1c109d2014-04-21 08:14:18 -07003815 && r_type != R_ALPHA_TLSGD)
3816 continue;
Richard Henderson252b5131999-05-03 07:29:11 +00003817 }
3818
3819 /* Get the value of the symbol referred to by the reloc. */
Richard Hendersoncc03ec82003-01-22 00:47:58 +00003820 if (r_symndx < symtab_hdr->sh_info)
Richard Henderson252b5131999-05-03 07:29:11 +00003821 {
3822 /* A local symbol. */
Alan Modra6cdc0cc2002-07-07 09:10:41 +00003823 Elf_Internal_Sym *isym;
Alan Modra9ad5cbc2001-12-17 00:52:35 +00003824
Alan Modra6cdc0cc2002-07-07 09:10:41 +00003825 /* Read this BFD's local symbols. */
3826 if (isymbuf == NULL)
3827 {
3828 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
3829 if (isymbuf == NULL)
3830 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
3831 symtab_hdr->sh_info, 0,
3832 NULL, NULL, NULL);
3833 if (isymbuf == NULL)
3834 goto error_return;
3835 }
3836
Richard Hendersoncc03ec82003-01-22 00:47:58 +00003837 isym = isymbuf + r_symndx;
3838
3839 /* Given the symbol for a TLSLDM reloc is ignored, this also
3840 means forcing the symbol value to the tp base. */
3841 if (r_type == R_ALPHA_TLSLDM)
3842 {
3843 info.tsec = bfd_abs_section_ptr;
Alan Modrae1918d22003-11-04 06:16:39 +00003844 symval = alpha_get_tprel_base (info.link_info);
Richard Hendersoncc03ec82003-01-22 00:47:58 +00003845 }
Kazu Hiratafe8bc632000-12-09 01:54:51 +00003846 else
Richard Hendersoncc03ec82003-01-22 00:47:58 +00003847 {
3848 symval = isym->st_value;
3849 if (isym->st_shndx == SHN_UNDEF)
Alan Modra07d6d2b2017-12-06 09:26:00 +10303850 continue;
Richard Hendersoncc03ec82003-01-22 00:47:58 +00003851 else if (isym->st_shndx == SHN_ABS)
Alan Modra07d6d2b2017-12-06 09:26:00 +10303852 info.tsec = bfd_abs_section_ptr;
Richard Hendersoncc03ec82003-01-22 00:47:58 +00003853 else if (isym->st_shndx == SHN_COMMON)
Alan Modra07d6d2b2017-12-06 09:26:00 +10303854 info.tsec = bfd_com_section_ptr;
Richard Hendersoncc03ec82003-01-22 00:47:58 +00003855 else
Alan Modra07d6d2b2017-12-06 09:26:00 +10303856 info.tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
Richard Hendersoncc03ec82003-01-22 00:47:58 +00003857 }
Richard Henderson252b5131999-05-03 07:29:11 +00003858
3859 info.h = NULL;
Alan Modra6cdc0cc2002-07-07 09:10:41 +00003860 info.other = isym->st_other;
Jakub Jelinekc328dc32003-02-07 09:30:33 +00003861 if (local_got_entries)
3862 info.first_gotent = &local_got_entries[r_symndx];
3863 else
3864 {
3865 info.first_gotent = &info.gotent;
3866 info.gotent = NULL;
3867 }
Richard Henderson252b5131999-05-03 07:29:11 +00003868 }
3869 else
3870 {
3871 unsigned long indx;
3872 struct alpha_elf_link_hash_entry *h;
3873
Richard Hendersoncc03ec82003-01-22 00:47:58 +00003874 indx = r_symndx - symtab_hdr->sh_info;
Richard Henderson252b5131999-05-03 07:29:11 +00003875 h = alpha_elf_sym_hashes (abfd)[indx];
3876 BFD_ASSERT (h != NULL);
3877
3878 while (h->root.root.type == bfd_link_hash_indirect
3879 || h->root.root.type == bfd_link_hash_warning)
3880 h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
3881
Richard Henderson4a67a092002-06-02 06:23:30 +00003882 /* If the symbol is undefined, we can't do anything with it. */
Richard Hendersond6ad34f2005-05-22 22:13:21 +00003883 if (h->root.root.type == bfd_link_hash_undefined)
Richard Henderson4a67a092002-06-02 06:23:30 +00003884 continue;
3885
Richard Hendersond6ad34f2005-05-22 22:13:21 +00003886 /* If the symbol isn't defined in the current module,
3887 again we can't do anything. */
3888 if (h->root.root.type == bfd_link_hash_undefweak)
3889 {
3890 info.tsec = bfd_abs_section_ptr;
3891 symval = 0;
3892 }
3893 else if (!h->root.def_regular)
Richard Hendersoncc03ec82003-01-22 00:47:58 +00003894 {
3895 /* Except for TLSGD relocs, which can sometimes be
3896 relaxed to GOTTPREL relocs. */
3897 if (r_type != R_ALPHA_TLSGD)
3898 continue;
3899 info.tsec = bfd_abs_section_ptr;
3900 symval = 0;
3901 }
3902 else
3903 {
3904 info.tsec = h->root.root.u.def.section;
3905 symval = h->root.root.u.def.value;
3906 }
Richard Henderson4a67a092002-06-02 06:23:30 +00003907
Richard Henderson252b5131999-05-03 07:29:11 +00003908 info.h = h;
Richard Henderson252b5131999-05-03 07:29:11 +00003909 info.other = h->root.other;
Richard Henderson9e756d62002-06-02 02:28:45 +00003910 info.first_gotent = &h->got_entries;
Richard Henderson252b5131999-05-03 07:29:11 +00003911 }
3912
3913 /* Search for the got entry to be used by this relocation. */
Richard Henderson9e756d62002-06-02 02:28:45 +00003914 for (gotent = *info.first_gotent; gotent ; gotent = gotent->next)
3915 if (gotent->gotobj == info.gotobj
3916 && gotent->reloc_type == r_type
3917 && gotent->addend == irel->r_addend)
3918 break;
Richard Henderson252b5131999-05-03 07:29:11 +00003919 info.gotent = gotent;
3920
3921 symval += info.tsec->output_section->vma + info.tsec->output_offset;
3922 symval += irel->r_addend;
3923
Richard Henderson9e756d62002-06-02 02:28:45 +00003924 switch (r_type)
Richard Henderson252b5131999-05-03 07:29:11 +00003925 {
Richard Henderson9e756d62002-06-02 02:28:45 +00003926 case R_ALPHA_LITERAL:
3927 BFD_ASSERT(info.gotent != NULL);
3928
3929 /* If there exist LITUSE relocations immediately following, this
3930 opens up all sorts of interesting optimizations, because we
3931 now know every location that this address load is used. */
3932 if (irel+1 < irelend
3933 && ELF64_R_TYPE (irel[1].r_info) == R_ALPHA_LITUSE)
3934 {
3935 if (!elf64_alpha_relax_with_lituse (&info, symval, irel))
3936 goto error_return;
3937 }
3938 else
3939 {
3940 if (!elf64_alpha_relax_got_load (&info, symval, irel, r_type))
3941 goto error_return;
3942 }
3943 break;
3944
Richard Henderson9e756d62002-06-02 02:28:45 +00003945 case R_ALPHA_GOTDTPREL:
3946 case R_ALPHA_GOTTPREL:
3947 BFD_ASSERT(info.gotent != NULL);
3948 if (!elf64_alpha_relax_got_load (&info, symval, irel, r_type))
Richard Henderson252b5131999-05-03 07:29:11 +00003949 goto error_return;
Richard Henderson9e756d62002-06-02 02:28:45 +00003950 break;
3951
3952 case R_ALPHA_TLSGD:
3953 case R_ALPHA_TLSLDM:
3954 BFD_ASSERT(info.gotent != NULL);
3955 if (!elf64_alpha_relax_tls_get_addr (&info, symval, irel,
3956 r_type == R_ALPHA_TLSGD))
3957 goto error_return;
3958 break;
Richard Henderson252b5131999-05-03 07:29:11 +00003959 }
3960 }
3961
Alan Modra6cdc0cc2002-07-07 09:10:41 +00003962 if (isymbuf != NULL
3963 && symtab_hdr->contents != (unsigned char *) isymbuf)
Richard Henderson252b5131999-05-03 07:29:11 +00003964 {
Alan Modra6cdc0cc2002-07-07 09:10:41 +00003965 if (!link_info->keep_memory)
3966 free (isymbuf);
3967 else
3968 {
3969 /* Cache the symbols for elf_link_input_bfd. */
3970 symtab_hdr->contents = (unsigned char *) isymbuf;
3971 }
3972 }
3973
3974 if (info.contents != NULL
3975 && elf_section_data (sec)->this_hdr.contents != info.contents)
3976 {
3977 if (!info.changed_contents && !link_info->keep_memory)
3978 free (info.contents);
Richard Henderson252b5131999-05-03 07:29:11 +00003979 else
3980 {
3981 /* Cache the section contents for elf_link_input_bfd. */
3982 elf_section_data (sec)->this_hdr.contents = info.contents;
3983 }
3984 }
3985
Alan Modra6cdc0cc2002-07-07 09:10:41 +00003986 if (elf_section_data (sec)->relocs != internal_relocs)
Richard Henderson252b5131999-05-03 07:29:11 +00003987 {
Alan Modra6cdc0cc2002-07-07 09:10:41 +00003988 if (!info.changed_relocs)
3989 free (internal_relocs);
Richard Henderson252b5131999-05-03 07:29:11 +00003990 else
Alan Modra6cdc0cc2002-07-07 09:10:41 +00003991 elf_section_data (sec)->relocs = internal_relocs;
Richard Henderson252b5131999-05-03 07:29:11 +00003992 }
3993
3994 *again = info.changed_contents || info.changed_relocs;
3995
Alan Modra0a1b45a2021-03-31 10:30:54 +10303996 return true;
Richard Henderson252b5131999-05-03 07:29:11 +00003997
3998 error_return:
Alan Modrac9594982020-05-20 17:25:20 +09303999 if (symtab_hdr->contents != (unsigned char *) isymbuf)
Alan Modra6cdc0cc2002-07-07 09:10:41 +00004000 free (isymbuf);
Alan Modrac9594982020-05-20 17:25:20 +09304001 if (elf_section_data (sec)->this_hdr.contents != info.contents)
Alan Modra6cdc0cc2002-07-07 09:10:41 +00004002 free (info.contents);
Alan Modrac9594982020-05-20 17:25:20 +09304003 if (elf_section_data (sec)->relocs != internal_relocs)
Alan Modra6cdc0cc2002-07-07 09:10:41 +00004004 free (internal_relocs);
Alan Modra0a1b45a2021-03-31 10:30:54 +10304005 return false;
Richard Henderson252b5131999-05-03 07:29:11 +00004006}
4007
Richard Henderson1bbc9ce2003-01-21 08:59:25 +00004008/* Emit a dynamic relocation for (DYNINDX, RTYPE, ADDEND) at (SEC, OFFSET)
4009 into the next available slot in SREL. */
4010
4011static void
Richard Hendersona7519a32005-05-26 07:14:03 +00004012elf64_alpha_emit_dynrel (bfd *abfd, struct bfd_link_info *info,
4013 asection *sec, asection *srel, bfd_vma offset,
4014 long dynindx, long rtype, bfd_vma addend)
Richard Henderson1bbc9ce2003-01-21 08:59:25 +00004015{
4016 Elf_Internal_Rela outrel;
4017 bfd_byte *loc;
4018
4019 BFD_ASSERT (srel != NULL);
4020
4021 outrel.r_info = ELF64_R_INFO (dynindx, rtype);
4022 outrel.r_addend = addend;
4023
4024 offset = _bfd_elf_section_offset (abfd, info, sec, offset);
4025 if ((offset | 1) != (bfd_vma) -1)
4026 outrel.r_offset = sec->output_section->vma + sec->output_offset + offset;
4027 else
4028 memset (&outrel, 0, sizeof (outrel));
4029
4030 loc = srel->contents;
4031 loc += srel->reloc_count++ * sizeof (Elf64_External_Rela);
4032 bfd_elf64_swap_reloca_out (abfd, &outrel, loc);
Alan Modraeea61212004-06-24 04:46:28 +00004033 BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count <= srel->size);
Richard Henderson1bbc9ce2003-01-21 08:59:25 +00004034}
4035
Richard Henderson4a67a092002-06-02 06:23:30 +00004036/* Relocate an Alpha ELF section for a relocatable link.
4037
4038 We don't have to change anything unless the reloc is against a section
4039 symbol, in which case we have to adjust according to where the section
4040 symbol winds up in the output section. */
4041
Alan Modra0f684202021-03-29 09:38:15 +10304042static int
Richard Hendersona7519a32005-05-26 07:14:03 +00004043elf64_alpha_relocate_section_r (bfd *output_bfd ATTRIBUTE_UNUSED,
4044 struct bfd_link_info *info ATTRIBUTE_UNUSED,
4045 bfd *input_bfd, asection *input_section,
4046 bfd_byte *contents ATTRIBUTE_UNUSED,
4047 Elf_Internal_Rela *relocs,
4048 Elf_Internal_Sym *local_syms,
4049 asection **local_sections)
Richard Henderson4a67a092002-06-02 06:23:30 +00004050{
4051 unsigned long symtab_hdr_sh_info;
4052 Elf_Internal_Rela *rel;
4053 Elf_Internal_Rela *relend;
Alan Modraab96bf02007-03-07 08:54:35 +00004054 struct elf_link_hash_entry **sym_hashes;
Alan Modra0a1b45a2021-03-31 10:30:54 +10304055 bool ret_val = true;
Richard Henderson4a67a092002-06-02 06:23:30 +00004056
Nick Clifton0ffa91d2008-02-12 11:32:31 +00004057 symtab_hdr_sh_info = elf_symtab_hdr (input_bfd).sh_info;
Alan Modraab96bf02007-03-07 08:54:35 +00004058 sym_hashes = elf_sym_hashes (input_bfd);
Richard Henderson4a67a092002-06-02 06:23:30 +00004059
4060 relend = relocs + input_section->reloc_count;
4061 for (rel = relocs; rel < relend; rel++)
4062 {
4063 unsigned long r_symndx;
4064 Elf_Internal_Sym *sym;
4065 asection *sec;
4066 unsigned long r_type;
4067
Alan Modraab96bf02007-03-07 08:54:35 +00004068 r_type = ELF64_R_TYPE (rel->r_info);
Richard Henderson4a67a092002-06-02 06:23:30 +00004069 if (r_type >= R_ALPHA_max)
4070 {
Alan Modra4eca0222016-09-30 13:00:18 +09304071 _bfd_error_handler
Nick Clifton695344c2016-10-19 14:04:34 +01004072 /* xgettext:c-format */
Alan Modra0aa13fe2018-02-21 21:47:07 +10304073 (_("%pB: unsupported relocation type %#x"),
Alan Modrad0038682004-08-13 03:16:01 +00004074 input_bfd, (int) r_type);
Richard Henderson4a67a092002-06-02 06:23:30 +00004075 bfd_set_error (bfd_error_bad_value);
Alan Modra0a1b45a2021-03-31 10:30:54 +10304076 ret_val = false;
Richard Henderson4a67a092002-06-02 06:23:30 +00004077 continue;
4078 }
4079
Richard Henderson4a67a092002-06-02 06:23:30 +00004080 /* The symbol associated with GPDISP and LITUSE is
4081 immaterial. Only the addend is significant. */
4082 if (r_type == R_ALPHA_GPDISP || r_type == R_ALPHA_LITUSE)
4083 continue;
4084
Alan Modraab96bf02007-03-07 08:54:35 +00004085 r_symndx = ELF64_R_SYM (rel->r_info);
Richard Henderson4a67a092002-06-02 06:23:30 +00004086 if (r_symndx < symtab_hdr_sh_info)
4087 {
4088 sym = local_syms + r_symndx;
Alan Modraab96bf02007-03-07 08:54:35 +00004089 sec = local_sections[r_symndx];
Richard Henderson4a67a092002-06-02 06:23:30 +00004090 }
Alan Modraab96bf02007-03-07 08:54:35 +00004091 else
4092 {
4093 struct elf_link_hash_entry *h;
4094
4095 h = sym_hashes[r_symndx - symtab_hdr_sh_info];
4096
4097 while (h->root.type == bfd_link_hash_indirect
4098 || h->root.type == bfd_link_hash_warning)
4099 h = (struct elf_link_hash_entry *) h->root.u.i.link;
4100
4101 if (h->root.type != bfd_link_hash_defined
4102 && h->root.type != bfd_link_hash_defweak)
4103 continue;
4104
4105 sym = NULL;
4106 sec = h->root.u.def.section;
4107 }
4108
Alan Modradbaa2012012-04-24 05:12:40 +00004109 if (sec != NULL && discarded_section (sec))
Daniel Jacobowitze4067db2010-10-25 15:54:16 +00004110 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
Maciej W. Rozycki545fd462012-05-07 03:27:52 +00004111 rel, 1, relend,
4112 elf64_alpha_howto_table + r_type, 0,
Daniel Jacobowitze4067db2010-10-25 15:54:16 +00004113 contents);
Alan Modraab96bf02007-03-07 08:54:35 +00004114
4115 if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
4116 rel->r_addend += sec->output_offset;
Richard Henderson4a67a092002-06-02 06:23:30 +00004117 }
4118
4119 return ret_val;
4120}
4121
Richard Henderson252b5131999-05-03 07:29:11 +00004122/* Relocate an Alpha ELF section. */
4123
Alan Modra0f684202021-03-29 09:38:15 +10304124static int
Richard Hendersona7519a32005-05-26 07:14:03 +00004125elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
4126 bfd *input_bfd, asection *input_section,
4127 bfd_byte *contents, Elf_Internal_Rela *relocs,
4128 Elf_Internal_Sym *local_syms,
4129 asection **local_sections)
Richard Henderson252b5131999-05-03 07:29:11 +00004130{
Richard Henderson4a67a092002-06-02 06:23:30 +00004131 Elf_Internal_Shdr *symtab_hdr;
Richard Henderson252b5131999-05-03 07:29:11 +00004132 Elf_Internal_Rela *rel;
4133 Elf_Internal_Rela *relend;
Richard Henderson4a67a092002-06-02 06:23:30 +00004134 asection *sgot, *srel, *srelgot;
4135 bfd *dynobj, *gotobj;
4136 bfd_vma gp, tp_base, dtp_base;
4137 struct alpha_elf_got_entry **local_got_entries;
Alan Modra0a1b45a2021-03-31 10:30:54 +10304138 bool ret_val;
Richard Henderson252b5131999-05-03 07:29:11 +00004139
Nick Clifton0ffa91d2008-02-12 11:32:31 +00004140 BFD_ASSERT (is_alpha_elf (input_bfd));
H.J. Lu68ffbac2013-01-10 20:03:55 +00004141
Richard Henderson4a67a092002-06-02 06:23:30 +00004142 /* Handle relocatable links with a smaller loop. */
H.J. Lu0e1862b2015-08-18 05:51:03 -07004143 if (bfd_link_relocatable (info))
Richard Henderson4a67a092002-06-02 06:23:30 +00004144 return elf64_alpha_relocate_section_r (output_bfd, info, input_bfd,
4145 input_section, contents, relocs,
4146 local_syms, local_sections);
4147
4148 /* This is a final link. */
4149
Alan Modra0a1b45a2021-03-31 10:30:54 +10304150 ret_val = true;
Richard Henderson4a67a092002-06-02 06:23:30 +00004151
Nick Clifton0ffa91d2008-02-12 11:32:31 +00004152 symtab_hdr = &elf_symtab_hdr (input_bfd);
Richard Henderson4a67a092002-06-02 06:23:30 +00004153
4154 dynobj = elf_hash_table (info)->dynobj;
Alan Modrace558b82016-11-23 15:06:34 +10304155 srelgot = elf_hash_table (info)->srelgot;
Richard Henderson4a67a092002-06-02 06:23:30 +00004156
Richard Henderson32412782005-05-23 01:26:58 +00004157 if (input_section->flags & SEC_ALLOC)
4158 {
4159 const char *section_name;
4160 section_name = (bfd_elf_string_from_elf_section
4161 (input_bfd, elf_elfheader(input_bfd)->e_shstrndx,
Bernd Schmidtd4730f92010-10-04 14:13:10 +00004162 _bfd_elf_single_rel_hdr (input_section)->sh_name));
Richard Henderson32412782005-05-23 01:26:58 +00004163 BFD_ASSERT(section_name != NULL);
Alan Modra3d4d4302012-06-29 14:46:03 +00004164 srel = bfd_get_linker_section (dynobj, section_name);
Richard Henderson32412782005-05-23 01:26:58 +00004165 }
4166 else
4167 srel = NULL;
Richard Henderson4a67a092002-06-02 06:23:30 +00004168
4169 /* Find the gp value for this input bfd. */
4170 gotobj = alpha_elf_tdata (input_bfd)->gotobj;
4171 if (gotobj)
Richard Henderson252b5131999-05-03 07:29:11 +00004172 {
Richard Henderson4a67a092002-06-02 06:23:30 +00004173 sgot = alpha_elf_tdata (gotobj)->got;
4174 gp = _bfd_get_gp_value (gotobj);
4175 if (gp == 0)
Richard Henderson252b5131999-05-03 07:29:11 +00004176 {
Richard Henderson4a67a092002-06-02 06:23:30 +00004177 gp = (sgot->output_section->vma
4178 + sgot->output_offset
4179 + 0x8000);
4180 _bfd_set_gp_value (gotobj, gp);
4181 }
4182 }
4183 else
4184 {
4185 sgot = NULL;
4186 gp = 0;
Richard Henderson252b5131999-05-03 07:29:11 +00004187 }
4188
Richard Henderson4a67a092002-06-02 06:23:30 +00004189 local_got_entries = alpha_elf_tdata(input_bfd)->local_got_entries;
4190
Alan Modrae1918d22003-11-04 06:16:39 +00004191 if (elf_hash_table (info)->tls_sec != NULL)
Richard Henderson252b5131999-05-03 07:29:11 +00004192 {
Alan Modrae1918d22003-11-04 06:16:39 +00004193 dtp_base = alpha_get_dtprel_base (info);
4194 tp_base = alpha_get_tprel_base (info);
Richard Henderson4a67a092002-06-02 06:23:30 +00004195 }
4196 else
4197 dtp_base = tp_base = 0;
4198
4199 relend = relocs + input_section->reloc_count;
4200 for (rel = relocs; rel < relend; rel++)
4201 {
4202 struct alpha_elf_link_hash_entry *h = NULL;
Richard Henderson3765b1b2002-05-30 22:01:38 +00004203 struct alpha_elf_got_entry *gotent;
4204 bfd_reloc_status_type r;
Richard Henderson252b5131999-05-03 07:29:11 +00004205 reloc_howto_type *howto;
4206 unsigned long r_symndx;
Richard Henderson4a67a092002-06-02 06:23:30 +00004207 Elf_Internal_Sym *sym = NULL;
4208 asection *sec = NULL;
Richard Henderson3765b1b2002-05-30 22:01:38 +00004209 bfd_vma value;
Alan Modradc810e32001-09-18 09:57:26 +00004210 bfd_vma addend;
Alan Modra0a1b45a2021-03-31 10:30:54 +10304211 bool dynamic_symbol_p;
4212 bool unresolved_reloc = false;
4213 bool undef_weak_ref = false;
Richard Henderson3765b1b2002-05-30 22:01:38 +00004214 unsigned long r_type;
Richard Henderson252b5131999-05-03 07:29:11 +00004215
4216 r_type = ELF64_R_TYPE(rel->r_info);
Richard Henderson3765b1b2002-05-30 22:01:38 +00004217 if (r_type >= R_ALPHA_max)
Richard Henderson252b5131999-05-03 07:29:11 +00004218 {
Alan Modra4eca0222016-09-30 13:00:18 +09304219 _bfd_error_handler
Nick Clifton695344c2016-10-19 14:04:34 +01004220 /* xgettext:c-format */
Alan Modra0aa13fe2018-02-21 21:47:07 +10304221 (_("%pB: unsupported relocation type %#x"),
Alan Modrad0038682004-08-13 03:16:01 +00004222 input_bfd, (int) r_type);
Richard Henderson252b5131999-05-03 07:29:11 +00004223 bfd_set_error (bfd_error_bad_value);
Alan Modra0a1b45a2021-03-31 10:30:54 +10304224 ret_val = false;
Richard Henderson3765b1b2002-05-30 22:01:38 +00004225 continue;
Richard Henderson252b5131999-05-03 07:29:11 +00004226 }
Richard Henderson252b5131999-05-03 07:29:11 +00004227
Richard Henderson3765b1b2002-05-30 22:01:38 +00004228 howto = elf64_alpha_howto_table + r_type;
Richard Henderson252b5131999-05-03 07:29:11 +00004229 r_symndx = ELF64_R_SYM(rel->r_info);
4230
Richard Hendersoncc03ec82003-01-22 00:47:58 +00004231 /* The symbol for a TLSLDM reloc is ignored. Collapse the
Thomas Schwingecf356382010-09-24 12:14:26 +00004232 reloc to the STN_UNDEF (0) symbol so that they all match. */
Richard Hendersoncc03ec82003-01-22 00:47:58 +00004233 if (r_type == R_ALPHA_TLSLDM)
Thomas Schwingecf356382010-09-24 12:14:26 +00004234 r_symndx = STN_UNDEF;
Richard Hendersoncc03ec82003-01-22 00:47:58 +00004235
Richard Henderson252b5131999-05-03 07:29:11 +00004236 if (r_symndx < symtab_hdr->sh_info)
4237 {
Alan Modra8517fae2003-11-05 13:17:09 +00004238 asection *msec;
Richard Henderson252b5131999-05-03 07:29:11 +00004239 sym = local_syms + r_symndx;
4240 sec = local_sections[r_symndx];
Alan Modra8517fae2003-11-05 13:17:09 +00004241 msec = sec;
4242 value = _bfd_elf_rela_local_sym (output_bfd, sym, &msec, rel);
Richard Henderson3765b1b2002-05-30 22:01:38 +00004243
Thomas Schwingecf356382010-09-24 12:14:26 +00004244 /* If this is a tp-relative relocation against sym STN_UNDEF (0),
Richard Hendersoncc03ec82003-01-22 00:47:58 +00004245 this is hackery from relax_section. Force the value to
Richard Hendersonf9153602005-05-30 21:22:40 +00004246 be the tls module base. */
Thomas Schwingecf356382010-09-24 12:14:26 +00004247 if (r_symndx == STN_UNDEF
Richard Hendersoncc03ec82003-01-22 00:47:58 +00004248 && (r_type == R_ALPHA_TLSLDM
4249 || r_type == R_ALPHA_GOTTPREL
4250 || r_type == R_ALPHA_TPREL64
4251 || r_type == R_ALPHA_TPRELHI
4252 || r_type == R_ALPHA_TPRELLO
4253 || r_type == R_ALPHA_TPREL16))
Richard Hendersonf9153602005-05-30 21:22:40 +00004254 value = dtp_base;
Richard Hendersoncc03ec82003-01-22 00:47:58 +00004255
Richard Henderson4a67a092002-06-02 06:23:30 +00004256 if (local_got_entries)
4257 gotent = local_got_entries[r_symndx];
4258 else
4259 gotent = NULL;
Richard Henderson3765b1b2002-05-30 22:01:38 +00004260
4261 /* Need to adjust local GOT entries' addends for SEC_MERGE
4262 unless it has been done already. */
4263 if ((sec->flags & SEC_MERGE)
Richard Henderson048d8732002-06-02 08:35:51 +00004264 && ELF_ST_TYPE (sym->st_info) == STT_SECTION
Alan Modradbaa2012012-04-24 05:12:40 +00004265 && sec->sec_info_type == SEC_INFO_TYPE_MERGE
Richard Henderson048d8732002-06-02 08:35:51 +00004266 && gotent
4267 && !gotent->reloc_xlated)
Richard Henderson3765b1b2002-05-30 22:01:38 +00004268 {
4269 struct alpha_elf_got_entry *ent;
Richard Henderson3765b1b2002-05-30 22:01:38 +00004270
4271 for (ent = gotent; ent; ent = ent->next)
4272 {
4273 ent->reloc_xlated = 1;
4274 if (ent->use_count == 0)
4275 continue;
4276 msec = sec;
4277 ent->addend =
4278 _bfd_merged_section_offset (output_bfd, &msec,
4279 elf_section_data (sec)->
4280 sec_info,
Alan Modra753731e2004-05-22 01:56:31 +00004281 sym->st_value + ent->addend);
Richard Henderson3765b1b2002-05-30 22:01:38 +00004282 ent->addend -= sym->st_value;
4283 ent->addend += msec->output_section->vma
4284 + msec->output_offset
4285 - sec->output_section->vma
4286 - sec->output_offset;
4287 }
4288 }
4289
Alan Modra0a1b45a2021-03-31 10:30:54 +10304290 dynamic_symbol_p = false;
Richard Henderson252b5131999-05-03 07:29:11 +00004291 }
4292 else
4293 {
Alan Modra0a1b45a2021-03-31 10:30:54 +10304294 bool warned, ignored;
Nick Clifton560e09e2003-08-20 08:37:19 +00004295 struct elf_link_hash_entry *hh;
Alan Modrab2a8e762004-03-22 02:28:17 +00004296 struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
4297
4298 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
4299 r_symndx, symtab_hdr, sym_hashes,
4300 hh, sec, value,
H.J. Lu62d887d2013-11-05 10:29:44 -08004301 unresolved_reloc, warned, ignored);
Richard Henderson252b5131999-05-03 07:29:11 +00004302
Nick Clifton560e09e2003-08-20 08:37:19 +00004303 if (warned)
4304 continue;
Richard Henderson252b5131999-05-03 07:29:11 +00004305
Nick Clifton560e09e2003-08-20 08:37:19 +00004306 if (value == 0
4307 && ! unresolved_reloc
4308 && hh->root.type == bfd_link_hash_undefweak)
Alan Modra0a1b45a2021-03-31 10:30:54 +10304309 undef_weak_ref = true;
Richard Henderson3765b1b2002-05-30 22:01:38 +00004310
Nick Clifton560e09e2003-08-20 08:37:19 +00004311 h = (struct alpha_elf_link_hash_entry *) hh;
Alan Modra07d6d2b2017-12-06 09:26:00 +10304312 dynamic_symbol_p = alpha_elf_dynamic_symbol_p (&h->root, info);
Richard Henderson3765b1b2002-05-30 22:01:38 +00004313 gotent = h->got_entries;
Richard Henderson252b5131999-05-03 07:29:11 +00004314 }
Richard Henderson3765b1b2002-05-30 22:01:38 +00004315
Alan Modradbaa2012012-04-24 05:12:40 +00004316 if (sec != NULL && discarded_section (sec))
Daniel Jacobowitze4067db2010-10-25 15:54:16 +00004317 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
Maciej W. Rozycki545fd462012-05-07 03:27:52 +00004318 rel, 1, relend, howto, 0, contents);
Alan Modraab96bf02007-03-07 08:54:35 +00004319
Richard Henderson252b5131999-05-03 07:29:11 +00004320 addend = rel->r_addend;
Richard Henderson3765b1b2002-05-30 22:01:38 +00004321 value += addend;
4322
4323 /* Search for the proper got entry. */
4324 for (; gotent ; gotent = gotent->next)
4325 if (gotent->gotobj == gotobj
4326 && gotent->reloc_type == r_type
4327 && gotent->addend == addend)
4328 break;
Richard Henderson252b5131999-05-03 07:29:11 +00004329
4330 switch (r_type)
4331 {
4332 case R_ALPHA_GPDISP:
4333 {
4334 bfd_byte *p_ldah, *p_lda;
4335
4336 BFD_ASSERT(gp != 0);
4337
Richard Henderson3765b1b2002-05-30 22:01:38 +00004338 value = (input_section->output_section->vma
4339 + input_section->output_offset
4340 + rel->r_offset);
Richard Henderson252b5131999-05-03 07:29:11 +00004341
Richard Henderson3765b1b2002-05-30 22:01:38 +00004342 p_ldah = contents + rel->r_offset;
Richard Henderson252b5131999-05-03 07:29:11 +00004343 p_lda = p_ldah + rel->r_addend;
4344
Richard Henderson3765b1b2002-05-30 22:01:38 +00004345 r = elf64_alpha_do_reloc_gpdisp (input_bfd, gp - value,
Richard Henderson252b5131999-05-03 07:29:11 +00004346 p_ldah, p_lda);
4347 }
4348 break;
4349
Richard Henderson252b5131999-05-03 07:29:11 +00004350 case R_ALPHA_LITERAL:
Richard Henderson3765b1b2002-05-30 22:01:38 +00004351 BFD_ASSERT(sgot != NULL);
4352 BFD_ASSERT(gp != 0);
4353 BFD_ASSERT(gotent != NULL);
4354 BFD_ASSERT(gotent->use_count >= 1);
Richard Henderson252b5131999-05-03 07:29:11 +00004355
Richard Henderson3765b1b2002-05-30 22:01:38 +00004356 if (!gotent->reloc_done)
4357 {
4358 gotent->reloc_done = 1;
Richard Henderson252b5131999-05-03 07:29:11 +00004359
Richard Henderson3765b1b2002-05-30 22:01:38 +00004360 bfd_put_64 (output_bfd, value,
4361 sgot->contents + gotent->got_offset);
Jakub Jelinekf7460f52001-11-28 19:15:14 +00004362
Richard Henderson3765b1b2002-05-30 22:01:38 +00004363 /* If the symbol has been forced local, output a
4364 RELATIVE reloc, otherwise it will be handled in
4365 finish_dynamic_symbol. */
H.J. Lu0e1862b2015-08-18 05:51:03 -07004366 if (bfd_link_pic (info)
4367 && !dynamic_symbol_p
4368 && !undef_weak_ref)
Richard Henderson1bbc9ce2003-01-21 08:59:25 +00004369 elf64_alpha_emit_dynrel (output_bfd, info, sgot, srelgot,
4370 gotent->got_offset, 0,
4371 R_ALPHA_RELATIVE, value);
Richard Henderson3765b1b2002-05-30 22:01:38 +00004372 }
Richard Henderson252b5131999-05-03 07:29:11 +00004373
Richard Henderson3765b1b2002-05-30 22:01:38 +00004374 value = (sgot->output_section->vma
4375 + sgot->output_offset
4376 + gotent->got_offset);
4377 value -= gp;
Richard Henderson252b5131999-05-03 07:29:11 +00004378 goto default_reloc;
4379
4380 case R_ALPHA_GPREL32:
Richard Hendersonec1659c2003-04-09 20:08:14 +00004381 case R_ALPHA_GPREL16:
Richard Henderson252b5131999-05-03 07:29:11 +00004382 case R_ALPHA_GPRELLOW:
Richard Henderson3765b1b2002-05-30 22:01:38 +00004383 if (dynamic_symbol_p)
Alan Modra07d6d2b2017-12-06 09:26:00 +10304384 {
Alan Modra4eca0222016-09-30 13:00:18 +09304385 _bfd_error_handler
Nick Clifton695344c2016-10-19 14:04:34 +01004386 /* xgettext:c-format */
Alan Modra871b3ab2018-02-19 15:21:40 +10304387 (_("%pB: gp-relative relocation against dynamic symbol %s"),
Alan Modra07d6d2b2017-12-06 09:26:00 +10304388 input_bfd, h->root.root.root.string);
Alan Modra0a1b45a2021-03-31 10:30:54 +10304389 ret_val = false;
Alan Modra07d6d2b2017-12-06 09:26:00 +10304390 }
Richard Henderson252b5131999-05-03 07:29:11 +00004391 BFD_ASSERT(gp != 0);
Richard Henderson3765b1b2002-05-30 22:01:38 +00004392 value -= gp;
Richard Henderson252b5131999-05-03 07:29:11 +00004393 goto default_reloc;
4394
4395 case R_ALPHA_GPRELHIGH:
Richard Henderson3765b1b2002-05-30 22:01:38 +00004396 if (dynamic_symbol_p)
Alan Modra07d6d2b2017-12-06 09:26:00 +10304397 {
Alan Modra4eca0222016-09-30 13:00:18 +09304398 _bfd_error_handler
Nick Clifton695344c2016-10-19 14:04:34 +01004399 /* xgettext:c-format */
Alan Modra871b3ab2018-02-19 15:21:40 +10304400 (_("%pB: gp-relative relocation against dynamic symbol %s"),
Alan Modra07d6d2b2017-12-06 09:26:00 +10304401 input_bfd, h->root.root.root.string);
Alan Modra0a1b45a2021-03-31 10:30:54 +10304402 ret_val = false;
Alan Modra07d6d2b2017-12-06 09:26:00 +10304403 }
Richard Henderson252b5131999-05-03 07:29:11 +00004404 BFD_ASSERT(gp != 0);
Richard Henderson3765b1b2002-05-30 22:01:38 +00004405 value -= gp;
4406 value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
Richard Henderson252b5131999-05-03 07:29:11 +00004407 goto default_reloc;
4408
Richard Henderson252b5131999-05-03 07:29:11 +00004409 case R_ALPHA_HINT:
Richard Hendersonf94952d2001-09-11 18:21:11 +00004410 /* A call to a dynamic symbol is definitely out of range of
4411 the 16-bit displacement. Don't bother writing anything. */
Richard Henderson3765b1b2002-05-30 22:01:38 +00004412 if (dynamic_symbol_p)
Richard Hendersonf94952d2001-09-11 18:21:11 +00004413 {
4414 r = bfd_reloc_ok;
4415 break;
4416 }
Richard Henderson252b5131999-05-03 07:29:11 +00004417 /* The regular PC-relative stuff measures from the start of
4418 the instruction rather than the end. */
Richard Henderson3765b1b2002-05-30 22:01:38 +00004419 value -= 4;
4420 goto default_reloc;
4421
4422 case R_ALPHA_BRADDR:
4423 if (dynamic_symbol_p)
Alan Modra07d6d2b2017-12-06 09:26:00 +10304424 {
Alan Modra4eca0222016-09-30 13:00:18 +09304425 _bfd_error_handler
Nick Clifton695344c2016-10-19 14:04:34 +01004426 /* xgettext:c-format */
Alan Modra871b3ab2018-02-19 15:21:40 +10304427 (_("%pB: pc-relative relocation against dynamic symbol %s"),
Alan Modra07d6d2b2017-12-06 09:26:00 +10304428 input_bfd, h->root.root.root.string);
Alan Modra0a1b45a2021-03-31 10:30:54 +10304429 ret_val = false;
Alan Modra07d6d2b2017-12-06 09:26:00 +10304430 }
Richard Henderson3765b1b2002-05-30 22:01:38 +00004431 /* The regular PC-relative stuff measures from the start of
4432 the instruction rather than the end. */
4433 value -= 4;
Richard Henderson252b5131999-05-03 07:29:11 +00004434 goto default_reloc;
4435
Richard Henderson7793f4d2002-02-09 22:53:53 +00004436 case R_ALPHA_BRSGP:
4437 {
4438 int other;
4439 const char *name;
4440
4441 /* The regular PC-relative stuff measures from the start of
4442 the instruction rather than the end. */
Richard Henderson3765b1b2002-05-30 22:01:38 +00004443 value -= 4;
Richard Henderson7793f4d2002-02-09 22:53:53 +00004444
Richard Hendersonccf00ab2002-02-15 21:26:05 +00004445 /* The source and destination gp must be the same. Note that
4446 the source will always have an assigned gp, since we forced
4447 one in check_relocs, but that the destination may not, as
Kazu Hiratacedb70c2002-06-03 01:57:10 +00004448 it might not have had any relocations at all. Also take
Richard Hendersonccf00ab2002-02-15 21:26:05 +00004449 care not to crash if H is an undefined symbol. */
4450 if (h != NULL && sec != NULL
4451 && alpha_elf_tdata (sec->owner)->gotobj
Richard Henderson7793f4d2002-02-09 22:53:53 +00004452 && gotobj != alpha_elf_tdata (sec->owner)->gotobj)
4453 {
Alan Modra4eca0222016-09-30 13:00:18 +09304454 _bfd_error_handler
Nick Clifton695344c2016-10-19 14:04:34 +01004455 /* xgettext:c-format */
Alan Modra871b3ab2018-02-19 15:21:40 +10304456 (_("%pB: change in gp: BRSGP %s"),
Alan Modrad0038682004-08-13 03:16:01 +00004457 input_bfd, h->root.root.root.string);
Alan Modra0a1b45a2021-03-31 10:30:54 +10304458 ret_val = false;
Richard Henderson7793f4d2002-02-09 22:53:53 +00004459 }
4460
4461 /* The symbol should be marked either NOPV or STD_GPLOAD. */
4462 if (h != NULL)
4463 other = h->root.other;
4464 else
4465 other = sym->st_other;
4466 switch (other & STO_ALPHA_STD_GPLOAD)
4467 {
4468 case STO_ALPHA_NOPV:
Alan Modra07d6d2b2017-12-06 09:26:00 +10304469 break;
Richard Henderson7793f4d2002-02-09 22:53:53 +00004470 case STO_ALPHA_STD_GPLOAD:
Richard Henderson64e04ecd2002-10-15 01:07:52 +00004471 value += 8;
Richard Henderson7793f4d2002-02-09 22:53:53 +00004472 break;
4473 default:
4474 if (h != NULL)
4475 name = h->root.root.root.string;
4476 else
4477 {
4478 name = (bfd_elf_string_from_elf_section
4479 (input_bfd, symtab_hdr->sh_link, sym->st_name));
4480 if (name == NULL)
4481 name = _("<unknown>");
4482 else if (name[0] == 0)
Alan Modrafd361982019-09-16 20:25:17 +09304483 name = bfd_section_name (sec);
Richard Henderson7793f4d2002-02-09 22:53:53 +00004484 }
Alan Modra4eca0222016-09-30 13:00:18 +09304485 _bfd_error_handler
Nick Clifton695344c2016-10-19 14:04:34 +01004486 /* xgettext:c-format */
Alan Modra871b3ab2018-02-19 15:21:40 +10304487 (_("%pB: !samegp reloc against symbol without .prologue: %s"),
Alan Modrad0038682004-08-13 03:16:01 +00004488 input_bfd, name);
Alan Modra0a1b45a2021-03-31 10:30:54 +10304489 ret_val = false;
Richard Henderson7793f4d2002-02-09 22:53:53 +00004490 break;
4491 }
4492
4493 goto default_reloc;
4494 }
4495
Richard Henderson252b5131999-05-03 07:29:11 +00004496 case R_ALPHA_REFLONG:
4497 case R_ALPHA_REFQUAD:
Richard Henderson3765b1b2002-05-30 22:01:38 +00004498 case R_ALPHA_DTPREL64:
4499 case R_ALPHA_TPREL64:
Richard Henderson252b5131999-05-03 07:29:11 +00004500 {
Richard Henderson1bbc9ce2003-01-21 08:59:25 +00004501 long dynindx, dyntype = r_type;
4502 bfd_vma dynaddend;
Richard Henderson252b5131999-05-03 07:29:11 +00004503
4504 /* Careful here to remember RELATIVE relocations for global
4505 variables for symbolic shared objects. */
4506
Richard Henderson3765b1b2002-05-30 22:01:38 +00004507 if (dynamic_symbol_p)
Richard Henderson252b5131999-05-03 07:29:11 +00004508 {
4509 BFD_ASSERT(h->root.dynindx != -1);
Richard Henderson1bbc9ce2003-01-21 08:59:25 +00004510 dynindx = h->root.dynindx;
4511 dynaddend = addend;
Richard Henderson3765b1b2002-05-30 22:01:38 +00004512 addend = 0, value = 0;
4513 }
4514 else if (r_type == R_ALPHA_DTPREL64)
4515 {
Alan Modrae1918d22003-11-04 06:16:39 +00004516 BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
Richard Henderson3765b1b2002-05-30 22:01:38 +00004517 value -= dtp_base;
4518 goto default_reloc;
4519 }
4520 else if (r_type == R_ALPHA_TPREL64)
4521 {
Alan Modrae1918d22003-11-04 06:16:39 +00004522 BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
Alan Modra3cbc1e52015-08-19 11:57:40 +09304523 if (!bfd_link_dll (info))
Richard Henderson1bbc9ce2003-01-21 08:59:25 +00004524 {
4525 value -= tp_base;
4526 goto default_reloc;
4527 }
4528 dynindx = 0;
4529 dynaddend = value - dtp_base;
Richard Henderson252b5131999-05-03 07:29:11 +00004530 }
H.J. Lu0e1862b2015-08-18 05:51:03 -07004531 else if (bfd_link_pic (info)
Thomas Schwingecf356382010-09-24 12:14:26 +00004532 && r_symndx != STN_UNDEF
Richard Hendersond6ad34f2005-05-22 22:13:21 +00004533 && (input_section->flags & SEC_ALLOC)
Alan Modra1d5316a2011-10-19 07:17:21 +00004534 && !undef_weak_ref
4535 && !(unresolved_reloc
4536 && (_bfd_elf_section_offset (output_bfd, info,
4537 input_section,
4538 rel->r_offset)
4539 == (bfd_vma) -1)))
Richard Henderson252b5131999-05-03 07:29:11 +00004540 {
Richard Henderson3765b1b2002-05-30 22:01:38 +00004541 if (r_type == R_ALPHA_REFLONG)
4542 {
Alan Modra4eca0222016-09-30 13:00:18 +09304543 _bfd_error_handler
Nick Clifton695344c2016-10-19 14:04:34 +01004544 /* xgettext:c-format */
Alan Modra871b3ab2018-02-19 15:21:40 +10304545 (_("%pB: unhandled dynamic relocation against %s"),
Alan Modrad0038682004-08-13 03:16:01 +00004546 input_bfd,
Richard Henderson3765b1b2002-05-30 22:01:38 +00004547 h->root.root.root.string);
Alan Modra0a1b45a2021-03-31 10:30:54 +10304548 ret_val = false;
Richard Henderson3765b1b2002-05-30 22:01:38 +00004549 }
Richard Henderson1bbc9ce2003-01-21 08:59:25 +00004550 dynindx = 0;
4551 dyntype = R_ALPHA_RELATIVE;
4552 dynaddend = value;
Richard Henderson252b5131999-05-03 07:29:11 +00004553 }
4554 else
4555 goto default_reloc;
4556
Richard Henderson32412782005-05-23 01:26:58 +00004557 if (input_section->flags & SEC_ALLOC)
4558 elf64_alpha_emit_dynrel (output_bfd, info, input_section,
4559 srel, rel->r_offset, dynindx,
4560 dyntype, dynaddend);
Richard Henderson252b5131999-05-03 07:29:11 +00004561 }
4562 goto default_reloc;
4563
Richard Henderson3765b1b2002-05-30 22:01:38 +00004564 case R_ALPHA_SREL16:
Richard Henderson84de6042002-05-02 17:46:59 +00004565 case R_ALPHA_SREL32:
4566 case R_ALPHA_SREL64:
Richard Henderson3765b1b2002-05-30 22:01:38 +00004567 if (dynamic_symbol_p)
Alan Modra07d6d2b2017-12-06 09:26:00 +10304568 {
Alan Modra4eca0222016-09-30 13:00:18 +09304569 _bfd_error_handler
Nick Clifton695344c2016-10-19 14:04:34 +01004570 /* xgettext:c-format */
Alan Modra871b3ab2018-02-19 15:21:40 +10304571 (_("%pB: pc-relative relocation against dynamic symbol %s"),
Alan Modra07d6d2b2017-12-06 09:26:00 +10304572 input_bfd, h->root.root.root.string);
Alan Modra0a1b45a2021-03-31 10:30:54 +10304573 ret_val = false;
Alan Modra07d6d2b2017-12-06 09:26:00 +10304574 }
Alan Modra3cbc1e52015-08-19 11:57:40 +09304575 else if (bfd_link_pic (info)
H.J. Lu0e1862b2015-08-18 05:51:03 -07004576 && undef_weak_ref)
Alan Modra07d6d2b2017-12-06 09:26:00 +10304577 {
Alan Modra4eca0222016-09-30 13:00:18 +09304578 _bfd_error_handler
Nick Clifton695344c2016-10-19 14:04:34 +01004579 /* xgettext:c-format */
Alan Modra871b3ab2018-02-19 15:21:40 +10304580 (_("%pB: pc-relative relocation against undefined weak symbol %s"),
Alan Modra07d6d2b2017-12-06 09:26:00 +10304581 input_bfd, h->root.root.root.string);
Alan Modra0a1b45a2021-03-31 10:30:54 +10304582 ret_val = false;
Alan Modra07d6d2b2017-12-06 09:26:00 +10304583 }
Richard Hendersond6ad34f2005-05-22 22:13:21 +00004584
Richard Henderson3765b1b2002-05-30 22:01:38 +00004585
Richard Henderson84de6042002-05-02 17:46:59 +00004586 /* ??? .eh_frame references to discarded sections will be smashed
4587 to relocations against SHN_UNDEF. The .eh_frame format allows
4588 NULL to be encoded as 0 in any format, so this works here. */
Alan Modra1d5316a2011-10-19 07:17:21 +00004589 if (r_symndx == STN_UNDEF
4590 || (unresolved_reloc
4591 && _bfd_elf_section_offset (output_bfd, info,
4592 input_section,
4593 rel->r_offset) == (bfd_vma) -1))
Richard Henderson84de6042002-05-02 17:46:59 +00004594 howto = (elf64_alpha_howto_table
4595 + (r_type - R_ALPHA_SREL32 + R_ALPHA_REFLONG));
4596 goto default_reloc;
4597
Richard Henderson3765b1b2002-05-30 22:01:38 +00004598 case R_ALPHA_TLSLDM:
4599 /* Ignore the symbol for the relocation. The result is always
4600 the current module. */
4601 dynamic_symbol_p = 0;
4602 /* FALLTHRU */
4603
4604 case R_ALPHA_TLSGD:
4605 if (!gotent->reloc_done)
4606 {
4607 gotent->reloc_done = 1;
4608
4609 /* Note that the module index for the main program is 1. */
H.J. Lu0e1862b2015-08-18 05:51:03 -07004610 bfd_put_64 (output_bfd,
4611 !bfd_link_pic (info) && !dynamic_symbol_p,
Richard Henderson3765b1b2002-05-30 22:01:38 +00004612 sgot->contents + gotent->got_offset);
4613
4614 /* If the symbol has been forced local, output a
4615 DTPMOD64 reloc, otherwise it will be handled in
4616 finish_dynamic_symbol. */
H.J. Lu0e1862b2015-08-18 05:51:03 -07004617 if (bfd_link_pic (info) && !dynamic_symbol_p)
Richard Henderson1bbc9ce2003-01-21 08:59:25 +00004618 elf64_alpha_emit_dynrel (output_bfd, info, sgot, srelgot,
4619 gotent->got_offset, 0,
4620 R_ALPHA_DTPMOD64, 0);
Richard Henderson3765b1b2002-05-30 22:01:38 +00004621
4622 if (dynamic_symbol_p || r_type == R_ALPHA_TLSLDM)
4623 value = 0;
4624 else
4625 {
Alan Modrae1918d22003-11-04 06:16:39 +00004626 BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
Alan Modra07d6d2b2017-12-06 09:26:00 +10304627 value -= dtp_base;
Richard Henderson3765b1b2002-05-30 22:01:38 +00004628 }
4629 bfd_put_64 (output_bfd, value,
4630 sgot->contents + gotent->got_offset + 8);
4631 }
4632
4633 value = (sgot->output_section->vma
4634 + sgot->output_offset
4635 + gotent->got_offset);
4636 value -= gp;
4637 goto default_reloc;
4638
4639 case R_ALPHA_DTPRELHI:
4640 case R_ALPHA_DTPRELLO:
4641 case R_ALPHA_DTPREL16:
4642 if (dynamic_symbol_p)
Alan Modra07d6d2b2017-12-06 09:26:00 +10304643 {
Alan Modra4eca0222016-09-30 13:00:18 +09304644 _bfd_error_handler
Nick Clifton695344c2016-10-19 14:04:34 +01004645 /* xgettext:c-format */
Alan Modra871b3ab2018-02-19 15:21:40 +10304646 (_("%pB: dtp-relative relocation against dynamic symbol %s"),
Alan Modra07d6d2b2017-12-06 09:26:00 +10304647 input_bfd, h->root.root.root.string);
Alan Modra0a1b45a2021-03-31 10:30:54 +10304648 ret_val = false;
Alan Modra07d6d2b2017-12-06 09:26:00 +10304649 }
Alan Modrae1918d22003-11-04 06:16:39 +00004650 BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
Richard Henderson3765b1b2002-05-30 22:01:38 +00004651 value -= dtp_base;
Richard Henderson9e756d62002-06-02 02:28:45 +00004652 if (r_type == R_ALPHA_DTPRELHI)
4653 value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
Richard Henderson3765b1b2002-05-30 22:01:38 +00004654 goto default_reloc;
4655
4656 case R_ALPHA_TPRELHI:
4657 case R_ALPHA_TPRELLO:
4658 case R_ALPHA_TPREL16:
Alan Modra3cbc1e52015-08-19 11:57:40 +09304659 if (bfd_link_dll (info))
Richard Henderson9e756d62002-06-02 02:28:45 +00004660 {
Alan Modra4eca0222016-09-30 13:00:18 +09304661 _bfd_error_handler
Nick Clifton695344c2016-10-19 14:04:34 +01004662 /* xgettext:c-format */
Alan Modra871b3ab2018-02-19 15:21:40 +10304663 (_("%pB: TLS local exec code cannot be linked into shared objects"),
Alan Modrad0038682004-08-13 03:16:01 +00004664 input_bfd);
Alan Modra0a1b45a2021-03-31 10:30:54 +10304665 ret_val = false;
Richard Henderson9e756d62002-06-02 02:28:45 +00004666 }
4667 else if (dynamic_symbol_p)
Alan Modra07d6d2b2017-12-06 09:26:00 +10304668 {
Alan Modra4eca0222016-09-30 13:00:18 +09304669 _bfd_error_handler
Nick Clifton695344c2016-10-19 14:04:34 +01004670 /* xgettext:c-format */
Alan Modra871b3ab2018-02-19 15:21:40 +10304671 (_("%pB: tp-relative relocation against dynamic symbol %s"),
Alan Modra07d6d2b2017-12-06 09:26:00 +10304672 input_bfd, h->root.root.root.string);
Alan Modra0a1b45a2021-03-31 10:30:54 +10304673 ret_val = false;
Alan Modra07d6d2b2017-12-06 09:26:00 +10304674 }
Alan Modrae1918d22003-11-04 06:16:39 +00004675 BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
Richard Henderson3765b1b2002-05-30 22:01:38 +00004676 value -= tp_base;
Richard Henderson9e756d62002-06-02 02:28:45 +00004677 if (r_type == R_ALPHA_TPRELHI)
4678 value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
Richard Henderson3765b1b2002-05-30 22:01:38 +00004679 goto default_reloc;
4680
4681 case R_ALPHA_GOTDTPREL:
4682 case R_ALPHA_GOTTPREL:
4683 BFD_ASSERT(sgot != NULL);
4684 BFD_ASSERT(gp != 0);
4685 BFD_ASSERT(gotent != NULL);
4686 BFD_ASSERT(gotent->use_count >= 1);
4687
4688 if (!gotent->reloc_done)
4689 {
4690 gotent->reloc_done = 1;
4691
4692 if (dynamic_symbol_p)
4693 value = 0;
4694 else
4695 {
Alan Modrae1918d22003-11-04 06:16:39 +00004696 BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
Richard Henderson1bbc9ce2003-01-21 08:59:25 +00004697 if (r_type == R_ALPHA_GOTDTPREL)
4698 value -= dtp_base;
Alan Modra28fbeab2019-05-28 15:06:47 +09304699 else if (bfd_link_executable (info))
Richard Henderson1bbc9ce2003-01-21 08:59:25 +00004700 value -= tp_base;
4701 else
4702 {
4703 elf64_alpha_emit_dynrel (output_bfd, info, sgot, srelgot,
4704 gotent->got_offset, 0,
4705 R_ALPHA_TPREL64,
4706 value - dtp_base);
4707 value = 0;
4708 }
Richard Henderson3765b1b2002-05-30 22:01:38 +00004709 }
4710 bfd_put_64 (output_bfd, value,
4711 sgot->contents + gotent->got_offset);
4712 }
4713
4714 value = (sgot->output_section->vma
4715 + sgot->output_offset
4716 + gotent->got_offset);
4717 value -= gp;
4718 goto default_reloc;
4719
Richard Henderson252b5131999-05-03 07:29:11 +00004720 default:
4721 default_reloc:
4722 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
Richard Henderson3765b1b2002-05-30 22:01:38 +00004723 contents, rel->r_offset, value, 0);
Richard Henderson252b5131999-05-03 07:29:11 +00004724 break;
4725 }
4726
4727 switch (r)
4728 {
4729 case bfd_reloc_ok:
4730 break;
4731
4732 case bfd_reloc_overflow:
4733 {
4734 const char *name;
4735
Jakub Jelineked4de5e2001-12-17 22:44:12 +00004736 /* Don't warn if the overflow is due to pc relative reloc
4737 against discarded section. Section optimization code should
4738 handle it. */
4739
4740 if (r_symndx < symtab_hdr->sh_info
4741 && sec != NULL && howto->pc_relative
Alan Modradbaa2012012-04-24 05:12:40 +00004742 && discarded_section (sec))
Jakub Jelineked4de5e2001-12-17 22:44:12 +00004743 break;
4744
Richard Henderson252b5131999-05-03 07:29:11 +00004745 if (h != NULL)
H.J. Ludfeffb92004-10-21 15:28:33 +00004746 name = NULL;
Richard Henderson252b5131999-05-03 07:29:11 +00004747 else
4748 {
4749 name = (bfd_elf_string_from_elf_section
4750 (input_bfd, symtab_hdr->sh_link, sym->st_name));
4751 if (name == NULL)
Alan Modra0a1b45a2021-03-31 10:30:54 +10304752 return false;
Richard Henderson252b5131999-05-03 07:29:11 +00004753 if (*name == '\0')
Alan Modrafd361982019-09-16 20:25:17 +09304754 name = bfd_section_name (sec);
Richard Henderson252b5131999-05-03 07:29:11 +00004755 }
Alan Modra1a727022016-05-27 17:20:55 +09304756 (*info->callbacks->reloc_overflow)
4757 (info, (h ? &h->root.root : NULL), name, howto->name,
4758 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
Richard Henderson252b5131999-05-03 07:29:11 +00004759 }
4760 break;
4761
4762 default:
4763 case bfd_reloc_outofrange:
4764 abort ();
4765 }
4766 }
4767
Richard Hendersonf16fbd62001-09-09 06:58:06 +00004768 return ret_val;
Richard Henderson252b5131999-05-03 07:29:11 +00004769}
4770
4771/* Finish up dynamic symbol handling. We set the contents of various
4772 dynamic sections here. */
4773
Alan Modra0a1b45a2021-03-31 10:30:54 +10304774static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00004775elf64_alpha_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info,
4776 struct elf_link_hash_entry *h,
4777 Elf_Internal_Sym *sym)
Richard Henderson252b5131999-05-03 07:29:11 +00004778{
Richard Henderson6ec70572005-05-29 23:13:39 +00004779 struct alpha_elf_link_hash_entry *ah = (struct alpha_elf_link_hash_entry *)h;
Richard Henderson252b5131999-05-03 07:29:11 +00004780
Richard Henderson6ec70572005-05-29 23:13:39 +00004781 if (h->needs_plt)
Richard Henderson252b5131999-05-03 07:29:11 +00004782 {
4783 /* Fill in the .plt entry for this symbol. */
4784 asection *splt, *sgot, *srel;
4785 Elf_Internal_Rela outrel;
Alan Modra947216b2002-11-28 11:55:43 +00004786 bfd_byte *loc;
Richard Henderson252b5131999-05-03 07:29:11 +00004787 bfd_vma got_addr, plt_addr;
4788 bfd_vma plt_index;
4789 struct alpha_elf_got_entry *gotent;
4790
4791 BFD_ASSERT (h->dynindx != -1);
4792
Alan Modrace558b82016-11-23 15:06:34 +10304793 splt = elf_hash_table (info)->splt;
Richard Henderson252b5131999-05-03 07:29:11 +00004794 BFD_ASSERT (splt != NULL);
Alan Modrace558b82016-11-23 15:06:34 +10304795 srel = elf_hash_table (info)->srelplt;
Richard Henderson252b5131999-05-03 07:29:11 +00004796 BFD_ASSERT (srel != NULL);
Richard Henderson252b5131999-05-03 07:29:11 +00004797
Richard Henderson6ec70572005-05-29 23:13:39 +00004798 for (gotent = ah->got_entries; gotent ; gotent = gotent->next)
4799 if (gotent->reloc_type == R_ALPHA_LITERAL
4800 && gotent->use_count > 0)
4801 {
4802 unsigned int insn;
4803 int disp;
Richard Henderson252b5131999-05-03 07:29:11 +00004804
Richard Henderson6ec70572005-05-29 23:13:39 +00004805 sgot = alpha_elf_tdata (gotent->gotobj)->got;
4806 BFD_ASSERT (sgot != NULL);
Richard Henderson252b5131999-05-03 07:29:11 +00004807
Richard Henderson6ec70572005-05-29 23:13:39 +00004808 BFD_ASSERT (gotent->got_offset != -1);
4809 BFD_ASSERT (gotent->plt_offset != -1);
Richard Henderson252b5131999-05-03 07:29:11 +00004810
Richard Henderson6ec70572005-05-29 23:13:39 +00004811 got_addr = (sgot->output_section->vma
4812 + sgot->output_offset
4813 + gotent->got_offset);
4814 plt_addr = (splt->output_section->vma
4815 + splt->output_offset
4816 + gotent->plt_offset);
Richard Henderson252b5131999-05-03 07:29:11 +00004817
Richard Henderson6ec70572005-05-29 23:13:39 +00004818 plt_index = (gotent->plt_offset-PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
Richard Henderson252b5131999-05-03 07:29:11 +00004819
Richard Henderson6ec70572005-05-29 23:13:39 +00004820 /* Fill in the entry in the procedure linkage table. */
4821 if (elf64_alpha_use_secureplt)
4822 {
4823 disp = (PLT_HEADER_SIZE - 4) - (gotent->plt_offset + 4);
4824 insn = INSN_AD (INSN_BR, 31, disp);
4825 bfd_put_32 (output_bfd, insn,
4826 splt->contents + gotent->plt_offset);
Richard Henderson252b5131999-05-03 07:29:11 +00004827
Richard Henderson6ec70572005-05-29 23:13:39 +00004828 plt_index = ((gotent->plt_offset - NEW_PLT_HEADER_SIZE)
4829 / NEW_PLT_ENTRY_SIZE);
4830 }
4831 else
4832 {
4833 disp = -(gotent->plt_offset + 4);
4834 insn = INSN_AD (INSN_BR, 28, disp);
4835 bfd_put_32 (output_bfd, insn,
4836 splt->contents + gotent->plt_offset);
4837 bfd_put_32 (output_bfd, INSN_UNOP,
4838 splt->contents + gotent->plt_offset + 4);
4839 bfd_put_32 (output_bfd, INSN_UNOP,
4840 splt->contents + gotent->plt_offset + 8);
Richard Henderson252b5131999-05-03 07:29:11 +00004841
Richard Henderson6ec70572005-05-29 23:13:39 +00004842 plt_index = ((gotent->plt_offset - OLD_PLT_HEADER_SIZE)
4843 / OLD_PLT_ENTRY_SIZE);
4844 }
Richard Henderson252b5131999-05-03 07:29:11 +00004845
Richard Henderson6ec70572005-05-29 23:13:39 +00004846 /* Fill in the entry in the .rela.plt section. */
4847 outrel.r_offset = got_addr;
4848 outrel.r_info = ELF64_R_INFO(h->dynindx, R_ALPHA_JMP_SLOT);
4849 outrel.r_addend = 0;
Richard Henderson252b5131999-05-03 07:29:11 +00004850
Richard Henderson6ec70572005-05-29 23:13:39 +00004851 loc = srel->contents + plt_index * sizeof (Elf64_External_Rela);
4852 bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
Richard Henderson252b5131999-05-03 07:29:11 +00004853
Richard Henderson6ec70572005-05-29 23:13:39 +00004854 /* Fill in the entry in the .got. */
4855 bfd_put_64 (output_bfd, plt_addr,
4856 sgot->contents + gotent->got_offset);
4857 }
Richard Henderson252b5131999-05-03 07:29:11 +00004858 }
4859 else if (alpha_elf_dynamic_symbol_p (h, info))
4860 {
4861 /* Fill in the dynamic relocations for this symbol's .got entries. */
4862 asection *srel;
Richard Henderson252b5131999-05-03 07:29:11 +00004863 struct alpha_elf_got_entry *gotent;
4864
Alan Modrace558b82016-11-23 15:06:34 +10304865 srel = elf_hash_table (info)->srelgot;
Richard Henderson252b5131999-05-03 07:29:11 +00004866 BFD_ASSERT (srel != NULL);
4867
Richard Henderson252b5131999-05-03 07:29:11 +00004868 for (gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries;
4869 gotent != NULL;
4870 gotent = gotent->next)
4871 {
Richard Hendersonf44f99a2002-06-02 03:58:40 +00004872 asection *sgot;
Richard Henderson1bbc9ce2003-01-21 08:59:25 +00004873 long r_type;
Richard Henderson3765b1b2002-05-30 22:01:38 +00004874
Richard Hendersonf44f99a2002-06-02 03:58:40 +00004875 if (gotent->use_count == 0)
4876 continue;
4877
4878 sgot = alpha_elf_tdata (gotent->gotobj)->got;
Richard Henderson3765b1b2002-05-30 22:01:38 +00004879
4880 r_type = gotent->reloc_type;
4881 switch (r_type)
4882 {
4883 case R_ALPHA_LITERAL:
4884 r_type = R_ALPHA_GLOB_DAT;
4885 break;
4886 case R_ALPHA_TLSGD:
4887 r_type = R_ALPHA_DTPMOD64;
4888 break;
4889 case R_ALPHA_GOTDTPREL:
4890 r_type = R_ALPHA_DTPREL64;
4891 break;
4892 case R_ALPHA_GOTTPREL:
4893 r_type = R_ALPHA_TPREL64;
4894 break;
4895 case R_ALPHA_TLSLDM:
4896 default:
4897 abort ();
4898 }
4899
H.J. Lu68ffbac2013-01-10 20:03:55 +00004900 elf64_alpha_emit_dynrel (output_bfd, info, sgot, srel,
Richard Henderson1bbc9ce2003-01-21 08:59:25 +00004901 gotent->got_offset, h->dynindx,
4902 r_type, gotent->addend);
Richard Henderson3765b1b2002-05-30 22:01:38 +00004903
4904 if (gotent->reloc_type == R_ALPHA_TLSGD)
H.J. Lu68ffbac2013-01-10 20:03:55 +00004905 elf64_alpha_emit_dynrel (output_bfd, info, sgot, srel,
Richard Henderson1bbc9ce2003-01-21 08:59:25 +00004906 gotent->got_offset + 8, h->dynindx,
4907 R_ALPHA_DTPREL64, gotent->addend);
Richard Henderson252b5131999-05-03 07:29:11 +00004908 }
4909 }
4910
4911 /* Mark some specially defined symbols as absolute. */
H.J. Lu9637f6e2012-09-02 12:17:27 +00004912 if (h == elf_hash_table (info)->hdynamic
Richard Sandiford22edb2f2006-02-27 08:48:28 +00004913 || h == elf_hash_table (info)->hgot
4914 || h == elf_hash_table (info)->hplt)
Richard Henderson252b5131999-05-03 07:29:11 +00004915 sym->st_shndx = SHN_ABS;
4916
Alan Modra0a1b45a2021-03-31 10:30:54 +10304917 return true;
Richard Henderson252b5131999-05-03 07:29:11 +00004918}
4919
4920/* Finish up the dynamic sections. */
4921
Alan Modra0a1b45a2021-03-31 10:30:54 +10304922static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00004923elf64_alpha_finish_dynamic_sections (bfd *output_bfd,
4924 struct bfd_link_info *info)
Richard Henderson252b5131999-05-03 07:29:11 +00004925{
4926 bfd *dynobj;
4927 asection *sdyn;
4928
4929 dynobj = elf_hash_table (info)->dynobj;
Alan Modra3d4d4302012-06-29 14:46:03 +00004930 sdyn = bfd_get_linker_section (dynobj, ".dynamic");
Richard Henderson252b5131999-05-03 07:29:11 +00004931
4932 if (elf_hash_table (info)->dynamic_sections_created)
4933 {
Richard Henderson6ec70572005-05-29 23:13:39 +00004934 asection *splt, *sgotplt, *srelaplt;
Richard Henderson252b5131999-05-03 07:29:11 +00004935 Elf64_External_Dyn *dyncon, *dynconend;
Richard Henderson6ec70572005-05-29 23:13:39 +00004936 bfd_vma plt_vma, gotplt_vma;
Richard Henderson252b5131999-05-03 07:29:11 +00004937
Alan Modrace558b82016-11-23 15:06:34 +10304938 splt = elf_hash_table (info)->splt;
4939 srelaplt = elf_hash_table (info)->srelplt;
Richard Henderson252b5131999-05-03 07:29:11 +00004940 BFD_ASSERT (splt != NULL && sdyn != NULL);
4941
Richard Henderson6ec70572005-05-29 23:13:39 +00004942 plt_vma = splt->output_section->vma + splt->output_offset;
4943
4944 gotplt_vma = 0;
4945 if (elf64_alpha_use_secureplt)
4946 {
Alan Modrace558b82016-11-23 15:06:34 +10304947 sgotplt = elf_hash_table (info)->sgotplt;
Richard Henderson6ec70572005-05-29 23:13:39 +00004948 BFD_ASSERT (sgotplt != NULL);
4949 if (sgotplt->size > 0)
4950 gotplt_vma = sgotplt->output_section->vma + sgotplt->output_offset;
4951 }
4952
Richard Henderson252b5131999-05-03 07:29:11 +00004953 dyncon = (Elf64_External_Dyn *) sdyn->contents;
Alan Modraeea61212004-06-24 04:46:28 +00004954 dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->size);
Richard Henderson252b5131999-05-03 07:29:11 +00004955 for (; dyncon < dynconend; dyncon++)
4956 {
4957 Elf_Internal_Dyn dyn;
Richard Henderson252b5131999-05-03 07:29:11 +00004958
4959 bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn);
4960
4961 switch (dyn.d_tag)
4962 {
4963 case DT_PLTGOT:
Richard Henderson6ec70572005-05-29 23:13:39 +00004964 dyn.d_un.d_ptr
4965 = elf64_alpha_use_secureplt ? gotplt_vma : plt_vma;
4966 break;
Richard Henderson252b5131999-05-03 07:29:11 +00004967 case DT_PLTRELSZ:
Richard Henderson6ec70572005-05-29 23:13:39 +00004968 dyn.d_un.d_val = srelaplt ? srelaplt->size : 0;
4969 break;
Richard Henderson252b5131999-05-03 07:29:11 +00004970 case DT_JMPREL:
Alan Modra4ade44b2016-05-13 11:48:56 +09304971 dyn.d_un.d_ptr = srelaplt ? (srelaplt->output_section->vma
4972 + srelaplt->output_offset) : 0;
Richard Henderson6ec70572005-05-29 23:13:39 +00004973 break;
Richard Henderson252b5131999-05-03 07:29:11 +00004974 }
4975
4976 bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
4977 }
4978
Richard Henderson6ec70572005-05-29 23:13:39 +00004979 /* Initialize the plt header. */
Alan Modraeea61212004-06-24 04:46:28 +00004980 if (splt->size > 0)
Richard Henderson252b5131999-05-03 07:29:11 +00004981 {
Richard Henderson6ec70572005-05-29 23:13:39 +00004982 unsigned int insn;
4983 int ofs;
Richard Henderson252b5131999-05-03 07:29:11 +00004984
Richard Henderson6ec70572005-05-29 23:13:39 +00004985 if (elf64_alpha_use_secureplt)
4986 {
4987 ofs = gotplt_vma - (plt_vma + PLT_HEADER_SIZE);
4988
4989 insn = INSN_ABC (INSN_SUBQ, 27, 28, 25);
4990 bfd_put_32 (output_bfd, insn, splt->contents);
4991
4992 insn = INSN_ABO (INSN_LDAH, 28, 28, (ofs + 0x8000) >> 16);
4993 bfd_put_32 (output_bfd, insn, splt->contents + 4);
4994
4995 insn = INSN_ABC (INSN_S4SUBQ, 25, 25, 25);
4996 bfd_put_32 (output_bfd, insn, splt->contents + 8);
4997
4998 insn = INSN_ABO (INSN_LDA, 28, 28, ofs);
4999 bfd_put_32 (output_bfd, insn, splt->contents + 12);
5000
5001 insn = INSN_ABO (INSN_LDQ, 27, 28, 0);
5002 bfd_put_32 (output_bfd, insn, splt->contents + 16);
5003
5004 insn = INSN_ABC (INSN_ADDQ, 25, 25, 25);
5005 bfd_put_32 (output_bfd, insn, splt->contents + 20);
5006
5007 insn = INSN_ABO (INSN_LDQ, 28, 28, 8);
5008 bfd_put_32 (output_bfd, insn, splt->contents + 24);
5009
5010 insn = INSN_AB (INSN_JMP, 31, 27);
5011 bfd_put_32 (output_bfd, insn, splt->contents + 28);
5012
5013 insn = INSN_AD (INSN_BR, 28, -PLT_HEADER_SIZE);
5014 bfd_put_32 (output_bfd, insn, splt->contents + 32);
5015 }
5016 else
5017 {
5018 insn = INSN_AD (INSN_BR, 27, 0); /* br $27, .+4 */
5019 bfd_put_32 (output_bfd, insn, splt->contents);
5020
5021 insn = INSN_ABO (INSN_LDQ, 27, 27, 12);
5022 bfd_put_32 (output_bfd, insn, splt->contents + 4);
5023
5024 insn = INSN_UNOP;
5025 bfd_put_32 (output_bfd, insn, splt->contents + 8);
5026
5027 insn = INSN_AB (INSN_JMP, 27, 27);
5028 bfd_put_32 (output_bfd, insn, splt->contents + 12);
5029
5030 /* The next two words will be filled in by ld.so. */
5031 bfd_put_64 (output_bfd, 0, splt->contents + 16);
5032 bfd_put_64 (output_bfd, 0, splt->contents + 24);
5033 }
Richard Henderson252b5131999-05-03 07:29:11 +00005034
Jakub Jelinekeecdbe52002-12-28 21:15:35 +00005035 elf_section_data (splt->output_section)->this_hdr.sh_entsize = 0;
Richard Henderson252b5131999-05-03 07:29:11 +00005036 }
5037 }
5038
Alan Modra0a1b45a2021-03-31 10:30:54 +10305039 return true;
Richard Henderson252b5131999-05-03 07:29:11 +00005040}
5041
Richard Henderson96e2734b2001-09-09 20:50:00 +00005042/* We need to use a special link routine to handle the .mdebug section.
5043 We need to merge all instances of these sections together, not write
5044 them all out sequentially. */
Richard Henderson252b5131999-05-03 07:29:11 +00005045
Alan Modra0a1b45a2021-03-31 10:30:54 +10305046static bool
Richard Hendersona7519a32005-05-26 07:14:03 +00005047elf64_alpha_final_link (bfd *abfd, struct bfd_link_info *info)
Richard Henderson252b5131999-05-03 07:29:11 +00005048{
5049 asection *o;
5050 struct bfd_link_order *p;
Richard Henderson96e2734b2001-09-09 20:50:00 +00005051 asection *mdebug_sec;
Richard Henderson252b5131999-05-03 07:29:11 +00005052 struct ecoff_debug_info debug;
5053 const struct ecoff_debug_swap *swap
5054 = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
5055 HDRR *symhdr = &debug.symbolic_header;
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00005056 void * mdebug_handle = NULL;
5057 struct alpha_elf_link_hash_table * htab;
5058
5059 htab = alpha_elf_hash_table (info);
5060 if (htab == NULL)
Alan Modra0a1b45a2021-03-31 10:30:54 +10305061 return false;
Richard Henderson252b5131999-05-03 07:29:11 +00005062
Richard Henderson96e2734b2001-09-09 20:50:00 +00005063 /* Go through the sections and collect the mdebug information. */
Richard Henderson252b5131999-05-03 07:29:11 +00005064 mdebug_sec = NULL;
Richard Henderson252b5131999-05-03 07:29:11 +00005065 for (o = abfd->sections; o != (asection *) NULL; o = o->next)
5066 {
Richard Henderson252b5131999-05-03 07:29:11 +00005067 if (strcmp (o->name, ".mdebug") == 0)
5068 {
5069 struct extsym_info einfo;
5070
5071 /* We have found the .mdebug section in the output file.
5072 Look through all the link_orders comprising it and merge
5073 the information together. */
5074 symhdr->magic = swap->sym_magic;
5075 /* FIXME: What should the version stamp be? */
5076 symhdr->vstamp = 0;
5077 symhdr->ilineMax = 0;
5078 symhdr->cbLine = 0;
5079 symhdr->idnMax = 0;
5080 symhdr->ipdMax = 0;
5081 symhdr->isymMax = 0;
5082 symhdr->ioptMax = 0;
5083 symhdr->iauxMax = 0;
5084 symhdr->issMax = 0;
5085 symhdr->issExtMax = 0;
5086 symhdr->ifdMax = 0;
5087 symhdr->crfd = 0;
5088 symhdr->iextMax = 0;
5089
5090 /* We accumulate the debugging information itself in the
5091 debug_info structure. */
5092 debug.line = NULL;
5093 debug.external_dnr = NULL;
5094 debug.external_pdr = NULL;
5095 debug.external_sym = NULL;
5096 debug.external_opt = NULL;
5097 debug.external_aux = NULL;
5098 debug.ss = NULL;
5099 debug.ssext = debug.ssext_end = NULL;
5100 debug.external_fdr = NULL;
5101 debug.external_rfd = NULL;
5102 debug.external_ext = debug.external_ext_end = NULL;
5103
5104 mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info);
Nick Clifton2c3fc382012-07-13 14:22:50 +00005105 if (mdebug_handle == NULL)
Alan Modra0a1b45a2021-03-31 10:30:54 +10305106 return false;
Richard Henderson252b5131999-05-03 07:29:11 +00005107
5108 if (1)
5109 {
5110 asection *s;
5111 EXTR esym;
Alan Modra52b9d212001-08-17 09:19:10 +00005112 bfd_vma last = 0;
Richard Henderson252b5131999-05-03 07:29:11 +00005113 unsigned int i;
5114 static const char * const name[] =
5115 {
5116 ".text", ".init", ".fini", ".data",
5117 ".rodata", ".sdata", ".sbss", ".bss"
5118 };
5119 static const int sc[] = { scText, scInit, scFini, scData,
5120 scRData, scSData, scSBss, scBss };
5121
5122 esym.jmptbl = 0;
5123 esym.cobol_main = 0;
5124 esym.weakext = 0;
5125 esym.reserved = 0;
5126 esym.ifd = ifdNil;
5127 esym.asym.iss = issNil;
5128 esym.asym.st = stLocal;
5129 esym.asym.reserved = 0;
5130 esym.asym.index = indexNil;
5131 for (i = 0; i < 8; i++)
5132 {
5133 esym.asym.sc = sc[i];
5134 s = bfd_get_section_by_name (abfd, name[i]);
5135 if (s != NULL)
5136 {
5137 esym.asym.value = s->vma;
Alan Modraeea61212004-06-24 04:46:28 +00005138 last = s->vma + s->size;
Richard Henderson252b5131999-05-03 07:29:11 +00005139 }
5140 else
5141 esym.asym.value = last;
5142
5143 if (! bfd_ecoff_debug_one_external (abfd, &debug, swap,
5144 name[i], &esym))
Alan Modra0a1b45a2021-03-31 10:30:54 +10305145 return false;
Richard Henderson252b5131999-05-03 07:29:11 +00005146 }
5147 }
5148
Alan Modra84232932005-05-04 11:00:28 +00005149 for (p = o->map_head.link_order;
Richard Henderson252b5131999-05-03 07:29:11 +00005150 p != (struct bfd_link_order *) NULL;
5151 p = p->next)
5152 {
5153 asection *input_section;
5154 bfd *input_bfd;
5155 const struct ecoff_debug_swap *input_swap;
5156 struct ecoff_debug_info input_debug;
5157 char *eraw_src;
5158 char *eraw_end;
5159
5160 if (p->type != bfd_indirect_link_order)
5161 {
Alan Modrafd96f802002-02-15 02:10:35 +00005162 if (p->type == bfd_data_link_order)
Richard Henderson252b5131999-05-03 07:29:11 +00005163 continue;
5164 abort ();
5165 }
5166
5167 input_section = p->u.indirect.section;
5168 input_bfd = input_section->owner;
5169
Nick Clifton0ffa91d2008-02-12 11:32:31 +00005170 if (! is_alpha_elf (input_bfd))
5171 /* I don't know what a non ALPHA ELF bfd would be
5172 doing with a .mdebug section, but I don't really
5173 want to deal with it. */
5174 continue;
Richard Henderson252b5131999-05-03 07:29:11 +00005175
5176 input_swap = (get_elf_backend_data (input_bfd)
5177 ->elf_backend_ecoff_debug_swap);
5178
Alan Modraeea61212004-06-24 04:46:28 +00005179 BFD_ASSERT (p->size == input_section->size);
Richard Henderson252b5131999-05-03 07:29:11 +00005180
5181 /* The ECOFF linking code expects that we have already
5182 read in the debugging information and set up an
5183 ecoff_debug_info structure, so we do that now. */
5184 if (!elf64_alpha_read_ecoff_info (input_bfd, input_section,
5185 &input_debug))
Alan Modra0a1b45a2021-03-31 10:30:54 +10305186 return false;
Richard Henderson252b5131999-05-03 07:29:11 +00005187
5188 if (! (bfd_ecoff_debug_accumulate
5189 (mdebug_handle, abfd, &debug, swap, input_bfd,
5190 &input_debug, input_swap, info)))
Alan Modra0a1b45a2021-03-31 10:30:54 +10305191 return false;
Richard Henderson252b5131999-05-03 07:29:11 +00005192
5193 /* Loop through the external symbols. For each one with
5194 interesting information, try to find the symbol in
5195 the linker global hash table and save the information
5196 for the output external symbols. */
Nick Clifton21d799b2009-09-25 19:13:27 +00005197 eraw_src = (char *) input_debug.external_ext;
Richard Henderson252b5131999-05-03 07:29:11 +00005198 eraw_end = (eraw_src
5199 + (input_debug.symbolic_header.iextMax
5200 * input_swap->external_ext_size));
5201 for (;
5202 eraw_src < eraw_end;
5203 eraw_src += input_swap->external_ext_size)
5204 {
5205 EXTR ext;
5206 const char *name;
5207 struct alpha_elf_link_hash_entry *h;
5208
Nick Clifton2c3fc382012-07-13 14:22:50 +00005209 (*input_swap->swap_ext_in) (input_bfd, eraw_src, &ext);
Richard Henderson252b5131999-05-03 07:29:11 +00005210 if (ext.asym.sc == scNil
5211 || ext.asym.sc == scUndefined
5212 || ext.asym.sc == scSUndefined)
5213 continue;
5214
5215 name = input_debug.ssext + ext.asym.iss;
Alan Modra0a1b45a2021-03-31 10:30:54 +10305216 h = alpha_elf_link_hash_lookup (htab, name, false, false, true);
Richard Henderson252b5131999-05-03 07:29:11 +00005217 if (h == NULL || h->esym.ifd != -2)
5218 continue;
5219
5220 if (ext.ifd != -1)
5221 {
5222 BFD_ASSERT (ext.ifd
5223 < input_debug.symbolic_header.ifdMax);
5224 ext.ifd = input_debug.ifdmap[ext.ifd];
5225 }
5226
5227 h->esym = ext;
5228 }
5229
5230 /* Free up the information we just read. */
5231 free (input_debug.line);
5232 free (input_debug.external_dnr);
5233 free (input_debug.external_pdr);
5234 free (input_debug.external_sym);
5235 free (input_debug.external_opt);
5236 free (input_debug.external_aux);
5237 free (input_debug.ss);
5238 free (input_debug.ssext);
5239 free (input_debug.external_fdr);
5240 free (input_debug.external_rfd);
5241 free (input_debug.external_ext);
5242
5243 /* Hack: reset the SEC_HAS_CONTENTS flag so that
5244 elf_link_input_bfd ignores this section. */
5245 input_section->flags &=~ SEC_HAS_CONTENTS;
5246 }
5247
Richard Henderson252b5131999-05-03 07:29:11 +00005248 /* Build the external symbol information. */
5249 einfo.abfd = abfd;
5250 einfo.info = info;
5251 einfo.debug = &debug;
5252 einfo.swap = swap;
Alan Modra0a1b45a2021-03-31 10:30:54 +10305253 einfo.failed = false;
Richard Henderson252b5131999-05-03 07:29:11 +00005254 elf_link_hash_traverse (elf_hash_table (info),
5255 elf64_alpha_output_extsym,
Nick Clifton2c3fc382012-07-13 14:22:50 +00005256 &einfo);
Richard Henderson252b5131999-05-03 07:29:11 +00005257 if (einfo.failed)
Alan Modra0a1b45a2021-03-31 10:30:54 +10305258 return false;
Richard Henderson252b5131999-05-03 07:29:11 +00005259
5260 /* Set the size of the .mdebug section. */
Alan Modraeea61212004-06-24 04:46:28 +00005261 o->size = bfd_ecoff_debug_size (abfd, &debug, swap);
Richard Henderson252b5131999-05-03 07:29:11 +00005262
5263 /* Skip this section later on (I don't think this currently
5264 matters, but someday it might). */
Alan Modra84232932005-05-04 11:00:28 +00005265 o->map_head.link_order = (struct bfd_link_order *) NULL;
Richard Henderson252b5131999-05-03 07:29:11 +00005266
5267 mdebug_sec = o;
5268 }
Richard Henderson252b5131999-05-03 07:29:11 +00005269 }
5270
5271 /* Invoke the regular ELF backend linker to do all the work. */
Alan Modrac152c792004-03-27 10:58:09 +00005272 if (! bfd_elf_final_link (abfd, info))
Alan Modra0a1b45a2021-03-31 10:30:54 +10305273 return false;
Richard Henderson252b5131999-05-03 07:29:11 +00005274
5275 /* Now write out the computed sections. */
5276
5277 /* The .got subsections... */
5278 {
5279 bfd *i, *dynobj = elf_hash_table(info)->dynobj;
Nick Clifton4dfe6ac2010-02-04 09:16:43 +00005280 for (i = htab->got_list;
Richard Henderson252b5131999-05-03 07:29:11 +00005281 i != NULL;
5282 i = alpha_elf_tdata(i)->got_link_next)
5283 {
5284 asection *sgot;
5285
5286 /* elf_bfd_final_link already did everything in dynobj. */
5287 if (i == dynobj)
5288 continue;
5289
5290 sgot = alpha_elf_tdata(i)->got;
5291 if (! bfd_set_section_contents (abfd, sgot->output_section,
Alan Modradc810e32001-09-18 09:57:26 +00005292 sgot->contents,
5293 (file_ptr) sgot->output_offset,
Alan Modraeea61212004-06-24 04:46:28 +00005294 sgot->size))
Alan Modra0a1b45a2021-03-31 10:30:54 +10305295 return false;
Richard Henderson252b5131999-05-03 07:29:11 +00005296 }
5297 }
5298
Richard Henderson252b5131999-05-03 07:29:11 +00005299 if (mdebug_sec != (asection *) NULL)
5300 {
5301 BFD_ASSERT (abfd->output_has_begun);
5302 if (! bfd_ecoff_write_accumulated_debug (mdebug_handle, abfd, &debug,
5303 swap, info,
5304 mdebug_sec->filepos))
Alan Modra0a1b45a2021-03-31 10:30:54 +10305305 return false;
Richard Henderson252b5131999-05-03 07:29:11 +00005306
5307 bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info);
5308 }
5309
Alan Modra0a1b45a2021-03-31 10:30:54 +10305310 return true;
Richard Henderson252b5131999-05-03 07:29:11 +00005311}
Jakub Jelinekfcfbdf32001-08-24 11:17:30 +00005312
5313static enum elf_reloc_type_class
Alan Modra7e612e92013-03-27 13:37:51 +00005314elf64_alpha_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
5315 const asection *rel_sec ATTRIBUTE_UNUSED,
5316 const Elf_Internal_Rela *rela)
Jakub Jelinekfcfbdf32001-08-24 11:17:30 +00005317{
Alan Modraf51e5522001-09-24 01:38:31 +00005318 switch ((int) ELF64_R_TYPE (rela->r_info))
Jakub Jelinekfcfbdf32001-08-24 11:17:30 +00005319 {
5320 case R_ALPHA_RELATIVE:
5321 return reloc_class_relative;
5322 case R_ALPHA_JMP_SLOT:
5323 return reloc_class_plt;
5324 case R_ALPHA_COPY:
5325 return reloc_class_copy;
5326 default:
5327 return reloc_class_normal;
5328 }
5329}
Richard Henderson252b5131999-05-03 07:29:11 +00005330
Alan Modrab35d2662005-07-05 06:23:37 +00005331static const struct bfd_elf_special_section elf64_alpha_special_sections[] =
H.J. Lu2f89ff82003-07-25 14:35:56 +00005332{
Alan Modra07d6d2b2017-12-06 09:26:00 +10305333 { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL },
Nick Clifton0112cd22006-09-16 18:12:17 +00005334 { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL },
Alan Modra07d6d2b2017-12-06 09:26:00 +10305335 { NULL, 0, 0, 0, 0 }
H.J. Lu2f89ff82003-07-25 14:35:56 +00005336};
5337
Richard Henderson252b5131999-05-03 07:29:11 +00005338/* ECOFF swapping routines. These are used when dealing with the
5339 .mdebug section, which is in the ECOFF debugging format. Copied
Kazu Hiratafe8bc632000-12-09 01:54:51 +00005340 from elf32-mips.c. */
Richard Henderson252b5131999-05-03 07:29:11 +00005341static const struct ecoff_debug_swap
5342elf64_alpha_ecoff_debug_swap =
5343{
5344 /* Symbol table magic number. */
5345 magicSym2,
5346 /* Alignment of debugging information. E.g., 4. */
5347 8,
5348 /* Sizes of external symbolic information. */
5349 sizeof (struct hdr_ext),
5350 sizeof (struct dnr_ext),
5351 sizeof (struct pdr_ext),
5352 sizeof (struct sym_ext),
5353 sizeof (struct opt_ext),
5354 sizeof (struct fdr_ext),
5355 sizeof (struct rfd_ext),
5356 sizeof (struct ext_ext),
5357 /* Functions to swap in external symbolic data. */
5358 ecoff_swap_hdr_in,
5359 ecoff_swap_dnr_in,
5360 ecoff_swap_pdr_in,
5361 ecoff_swap_sym_in,
5362 ecoff_swap_opt_in,
5363 ecoff_swap_fdr_in,
5364 ecoff_swap_rfd_in,
5365 ecoff_swap_ext_in,
5366 _bfd_ecoff_swap_tir_in,
5367 _bfd_ecoff_swap_rndx_in,
5368 /* Functions to swap out external symbolic data. */
5369 ecoff_swap_hdr_out,
5370 ecoff_swap_dnr_out,
5371 ecoff_swap_pdr_out,
5372 ecoff_swap_sym_out,
5373 ecoff_swap_opt_out,
5374 ecoff_swap_fdr_out,
5375 ecoff_swap_rfd_out,
5376 ecoff_swap_ext_out,
5377 _bfd_ecoff_swap_tir_out,
5378 _bfd_ecoff_swap_rndx_out,
5379 /* Function to read in symbolic data. */
5380 elf64_alpha_read_ecoff_info
5381};
5382
Jim Wilson70bcb142000-07-04 02:18:06 +00005383/* Use a non-standard hash bucket size of 8. */
5384
Alan Modra562ace62002-09-17 08:48:54 +00005385static const struct elf_size_info alpha_elf_size_info =
Jim Wilson70bcb142000-07-04 02:18:06 +00005386{
5387 sizeof (Elf64_External_Ehdr),
5388 sizeof (Elf64_External_Phdr),
5389 sizeof (Elf64_External_Shdr),
5390 sizeof (Elf64_External_Rel),
5391 sizeof (Elf64_External_Rela),
5392 sizeof (Elf64_External_Sym),
5393 sizeof (Elf64_External_Dyn),
5394 sizeof (Elf_External_Note),
5395 8,
5396 1,
Alan Modra45d6a902003-05-09 02:27:11 +00005397 64, 3,
Jim Wilson70bcb142000-07-04 02:18:06 +00005398 ELFCLASS64, EV_CURRENT,
5399 bfd_elf64_write_out_phdrs,
5400 bfd_elf64_write_shdrs_and_ehdr,
Alan Modra1489a3a2007-07-10 04:08:12 +00005401 bfd_elf64_checksum_contents,
Jim Wilson70bcb142000-07-04 02:18:06 +00005402 bfd_elf64_write_relocs,
Alan Modra73ff0d52002-06-05 13:32:02 +00005403 bfd_elf64_swap_symbol_in,
Jim Wilson70bcb142000-07-04 02:18:06 +00005404 bfd_elf64_swap_symbol_out,
5405 bfd_elf64_slurp_reloc_table,
5406 bfd_elf64_slurp_symbol_table,
5407 bfd_elf64_swap_dyn_in,
5408 bfd_elf64_swap_dyn_out,
Alan Modra947216b2002-11-28 11:55:43 +00005409 bfd_elf64_swap_reloc_in,
5410 bfd_elf64_swap_reloc_out,
5411 bfd_elf64_swap_reloca_in,
5412 bfd_elf64_swap_reloca_out
Jim Wilson70bcb142000-07-04 02:18:06 +00005413};
5414
Alan Modra6d00b592014-05-02 20:09:40 +09305415#define TARGET_LITTLE_SYM alpha_elf64_vec
Richard Henderson252b5131999-05-03 07:29:11 +00005416#define TARGET_LITTLE_NAME "elf64-alpha"
5417#define ELF_ARCH bfd_arch_alpha
H.J. Luae95ffa2010-08-25 14:53:45 +00005418#define ELF_TARGET_ID ALPHA_ELF_DATA
Andreas Jaeger56fc0282001-05-03 04:46:27 +00005419#define ELF_MACHINE_CODE EM_ALPHA
5420#define ELF_MAXPAGESIZE 0x10000
H.J. Lu24718e32006-05-30 16:45:32 +00005421#define ELF_COMMONPAGESIZE 0x2000
Richard Henderson252b5131999-05-03 07:29:11 +00005422
5423#define bfd_elf64_bfd_link_hash_table_create \
5424 elf64_alpha_bfd_link_hash_table_create
5425
5426#define bfd_elf64_bfd_reloc_type_lookup \
5427 elf64_alpha_bfd_reloc_type_lookup
Alan Modra157090f2007-03-26 12:23:03 +00005428#define bfd_elf64_bfd_reloc_name_lookup \
5429 elf64_alpha_bfd_reloc_name_lookup
Richard Henderson252b5131999-05-03 07:29:11 +00005430#define elf_info_to_howto \
5431 elf64_alpha_info_to_howto
5432
5433#define bfd_elf64_mkobject \
5434 elf64_alpha_mkobject
5435#define elf_backend_object_p \
5436 elf64_alpha_object_p
5437
5438#define elf_backend_section_from_shdr \
5439 elf64_alpha_section_from_shdr
Richard Henderson204692d2001-09-11 18:26:27 +00005440#define elf_backend_section_flags \
5441 elf64_alpha_section_flags
Richard Henderson252b5131999-05-03 07:29:11 +00005442#define elf_backend_fake_sections \
5443 elf64_alpha_fake_sections
5444
5445#define bfd_elf64_bfd_is_local_label_name \
5446 elf64_alpha_is_local_label_name
5447#define bfd_elf64_find_nearest_line \
5448 elf64_alpha_find_nearest_line
5449#define bfd_elf64_bfd_relax_section \
5450 elf64_alpha_relax_section
5451
5452#define elf_backend_add_symbol_hook \
5453 elf64_alpha_add_symbol_hook
Alan Modra13285a12007-10-18 09:13:51 +00005454#define elf_backend_relocs_compatible \
5455 _bfd_elf_relocs_compatible
Alan Modra6fc5bb52015-08-27 10:54:28 +09305456#define elf_backend_sort_relocs_p \
5457 elf64_alpha_sort_relocs_p
Richard Henderson252b5131999-05-03 07:29:11 +00005458#define elf_backend_check_relocs \
5459 elf64_alpha_check_relocs
5460#define elf_backend_create_dynamic_sections \
5461 elf64_alpha_create_dynamic_sections
5462#define elf_backend_adjust_dynamic_symbol \
5463 elf64_alpha_adjust_dynamic_symbol
Alan Modra747ffa72006-12-06 07:25:29 +00005464#define elf_backend_merge_symbol_attribute \
5465 elf64_alpha_merge_symbol_attribute
Richard Henderson48f4b4f2011-06-15 15:04:12 +00005466#define elf_backend_copy_indirect_symbol \
5467 elf64_alpha_copy_indirect_symbol
Richard Henderson252b5131999-05-03 07:29:11 +00005468#define elf_backend_always_size_sections \
5469 elf64_alpha_always_size_sections
5470#define elf_backend_size_dynamic_sections \
5471 elf64_alpha_size_dynamic_sections
Alan Modra74541ad2006-10-17 13:41:49 +00005472#define elf_backend_omit_section_dynsym \
Alan Modrad00dd7d2018-02-15 10:58:06 +10305473 _bfd_elf_omit_section_dynsym_all
Richard Henderson252b5131999-05-03 07:29:11 +00005474#define elf_backend_relocate_section \
5475 elf64_alpha_relocate_section
5476#define elf_backend_finish_dynamic_symbol \
5477 elf64_alpha_finish_dynamic_symbol
5478#define elf_backend_finish_dynamic_sections \
5479 elf64_alpha_finish_dynamic_sections
5480#define bfd_elf64_bfd_final_link \
5481 elf64_alpha_final_link
Jakub Jelinekfcfbdf32001-08-24 11:17:30 +00005482#define elf_backend_reloc_type_class \
5483 elf64_alpha_reloc_type_class
Richard Henderson252b5131999-05-03 07:29:11 +00005484
Richard Hendersone1173602011-03-29 21:18:16 +00005485#define elf_backend_can_gc_sections 1
5486#define elf_backend_gc_mark_hook elf64_alpha_gc_mark_hook
Richard Hendersone1173602011-03-29 21:18:16 +00005487
Richard Henderson252b5131999-05-03 07:29:11 +00005488#define elf_backend_ecoff_debug_swap \
5489 &elf64_alpha_ecoff_debug_swap
5490
Jim Wilson70bcb142000-07-04 02:18:06 +00005491#define elf_backend_size_info \
5492 alpha_elf_size_info
5493
H.J. Lu29ef7002005-07-08 00:26:53 +00005494#define elf_backend_special_sections \
5495 elf64_alpha_special_sections
H.J. Lu2f89ff82003-07-25 14:35:56 +00005496
H.J. Lu6f6fd152020-04-21 05:23:51 -07005497#define elf_backend_strip_zero_sized_dynamic_sections \
5498 _bfd_elf_strip_zero_sized_dynamic_sections
5499
Nick Clifton38b1a462000-12-12 19:23:16 +00005500/* A few constants that determine how the .plt section is set up. */
Richard Henderson252b5131999-05-03 07:29:11 +00005501#define elf_backend_want_got_plt 0
5502#define elf_backend_plt_readonly 0
5503#define elf_backend_want_plt_sym 1
5504#define elf_backend_got_header_size 0
Alan Modra64f52332016-11-23 15:07:17 +10305505#define elf_backend_dtrel_excludes_plt 1
Richard Henderson252b5131999-05-03 07:29:11 +00005506
5507#include "elf64-target.h"
Richard Henderson22380512002-10-15 17:14:51 +00005508
5509/* FreeBSD support. */
5510
5511#undef TARGET_LITTLE_SYM
Alan Modra6d00b592014-05-02 20:09:40 +09305512#define TARGET_LITTLE_SYM alpha_elf64_fbsd_vec
Richard Henderson22380512002-10-15 17:14:51 +00005513#undef TARGET_LITTLE_NAME
5514#define TARGET_LITTLE_NAME "elf64-alpha-freebsd"
H.J. Lud1036ac2007-03-14 02:56:45 +00005515#undef ELF_OSABI
5516#define ELF_OSABI ELFOSABI_FREEBSD
Richard Henderson22380512002-10-15 17:14:51 +00005517
5518/* The kernel recognizes executables as valid only if they carry a
5519 "FreeBSD" label in the ELF header. So we put this label on all
5520 executables and (for simplicity) also all other object files. */
5521
Alan Modra0a1b45a2021-03-31 10:30:54 +10305522static bool
Alan Modraed7e9d02019-11-18 17:09:40 +10305523elf64_alpha_fbsd_init_file_header (bfd *abfd, struct bfd_link_info *info)
Richard Henderson22380512002-10-15 17:14:51 +00005524{
5525 Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */
5526
Alan Modraed7e9d02019-11-18 17:09:40 +10305527 if (!_bfd_elf_init_file_header (abfd, info))
Alan Modra0a1b45a2021-03-31 10:30:54 +10305528 return false;
Alan Modraed7e9d02019-11-18 17:09:40 +10305529
Richard Henderson22380512002-10-15 17:14:51 +00005530 i_ehdrp = elf_elfheader (abfd);
5531
5532 /* Put an ABI label supported by FreeBSD >= 4.1. */
H.J. Lud1036ac2007-03-14 02:56:45 +00005533 i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
Richard Henderson22380512002-10-15 17:14:51 +00005534#ifdef OLD_FREEBSD_ABI_LABEL
5535 /* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */
5536 memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8);
5537#endif
Alan Modra0a1b45a2021-03-31 10:30:54 +10305538 return true;
Richard Henderson22380512002-10-15 17:14:51 +00005539}
5540
Alan Modraed7e9d02019-11-18 17:09:40 +10305541#undef elf_backend_init_file_header
5542#define elf_backend_init_file_header \
5543 elf64_alpha_fbsd_init_file_header
Richard Henderson22380512002-10-15 17:14:51 +00005544
Nick Clifton571fe012003-01-20 18:06:21 +00005545#undef elf64_bed
Richard Henderson22380512002-10-15 17:14:51 +00005546#define elf64_bed elf64_alpha_fbsd_bed
5547
5548#include "elf64-target.h"