]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/elf32-score.c
Automatic date update in version.in
[thirdparty/binutils-gdb.git] / bfd / elf32-score.c
CommitLineData
1c0d3aa6 1/* 32-bit ELF support for S+core.
fd67aa11 2 Copyright (C) 2006-2024 Free Software Foundation, Inc.
1c0d3aa6 3 Contributed by
c3b7224a 4 Brain.lin (brain.lin@sunplusct.com)
1c0d3aa6
NC
5 Mei Ligang (ligang@sunnorth.com.cn)
6 Pei-Lin Tsai (pltsai@sunplus.com)
7
8 This file is part of BFD, the Binary File Descriptor library.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
cd123cb7 12 the Free Software Foundation; either version 3 of the License, or
1c0d3aa6
NC
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
cd123cb7
NC
22 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23 MA 02110-1301, USA. */
1c0d3aa6 24
1c0d3aa6 25#include "sysdep.h"
3db64b00 26#include "bfd.h"
1c0d3aa6
NC
27#include "libbfd.h"
28#include "libiberty.h"
29#include "elf-bfd.h"
30#include "elf/score.h"
31#include "elf/common.h"
32#include "elf/internal.h"
33#include "hashtab.h"
c3b7224a 34#include "elf32-score.h"
1c0d3aa6
NC
35
36
c3b7224a
NC
37int score3 = 0;
38int score7 = 1;
1c0d3aa6 39
1c0d3aa6
NC
40/* The SCORE ELF linker needs additional information for each symbol in
41 the global hash table. */
1c0d3aa6
NC
42struct score_elf_link_hash_entry
43{
44 struct elf_link_hash_entry root;
45
46 /* Number of R_SCORE_ABS32, R_SCORE_REL32 relocs against this symbol. */
47 unsigned int possibly_dynamic_relocs;
48
49 /* If the R_SCORE_ABS32, R_SCORE_REL32 reloc is against a readonly section. */
0a1b45a2 50 bool readonly_reloc;
1c0d3aa6
NC
51
52 /* We must not create a stub for a symbol that has relocations related to
53 taking the function's address, i.e. any but R_SCORE_CALL15 ones. */
0a1b45a2 54 bool no_fn_stub;
1c0d3aa6
NC
55
56 /* Are we forced local? This will only be set if we have converted
57 the initial global GOT entry to a local GOT entry. */
0a1b45a2 58 bool forced_local;
1c0d3aa6
NC
59};
60
61/* Traverse a score ELF linker hash table. */
62#define score_elf_link_hash_traverse(table, func, info) \
0a1b45a2
AM
63 (elf_link_hash_traverse \
64 ((table), \
65 (bool (*) (struct elf_link_hash_entry *, void *)) (func), \
1c0d3aa6
NC
66 (info)))
67
1c0d3aa6
NC
68/* This structure is used to hold .got entries while estimating got sizes. */
69struct score_got_entry
70{
71 /* The input bfd in which the symbol is defined. */
72 bfd *abfd;
73 /* The index of the symbol, as stored in the relocation r_info, if
74 we have a local symbol; -1 otherwise. */
75 long symndx;
76 union
77 {
78 /* If abfd == NULL, an address that must be stored in the got. */
79 bfd_vma address;
80 /* If abfd != NULL && symndx != -1, the addend of the relocation
81 that should be added to the symbol value. */
82 bfd_vma addend;
83 /* If abfd != NULL && symndx == -1, the hash table entry
84 corresponding to a global symbol in the got (or, local, if
85 h->forced_local). */
86 struct score_elf_link_hash_entry *h;
87 } d;
88
89 /* The offset from the beginning of the .got section to the entry
90 corresponding to this symbol+addend. If it's a global symbol
91 whose offset is yet to be decided, it's going to be -1. */
92 long gotidx;
93};
94
95/* This structure is passed to score_elf_sort_hash_table_f when sorting
96 the dynamic symbols. */
97
98struct score_elf_hash_sort_data
99{
100 /* The symbol in the global GOT with the lowest dynamic symbol table index. */
101 struct elf_link_hash_entry *low;
102 /* The least dynamic symbol table index corresponding to a symbol with a GOT entry. */
103 long min_got_dynindx;
104 /* The greatest dynamic symbol table index corresponding to a symbol
105 with a GOT entry that is not referenced (e.g., a dynamic symbol
106 with dynamic relocations pointing to it from non-primary GOTs). */
107 long max_unref_got_dynindx;
108 /* The greatest dynamic symbol table index not corresponding to a
109 symbol without a GOT entry. */
110 long max_non_got_dynindx;
111};
112
113struct score_got_info
114{
115 /* The global symbol in the GOT with the lowest index in the dynamic
116 symbol table. */
117 struct elf_link_hash_entry *global_gotsym;
118 /* The number of global .got entries. */
119 unsigned int global_gotno;
120 /* The number of local .got entries. */
121 unsigned int local_gotno;
122 /* The number of local .got entries we have used. */
123 unsigned int assigned_gotno;
124 /* A hash table holding members of the got. */
125 struct htab *got_entries;
126 /* In multi-got links, a pointer to the next got (err, rather, most
127 of the time, it points to the previous got). */
128 struct score_got_info *next;
129};
130
131/* A structure used to count GOT entries, for GOT entry or ELF symbol table traversal. */
132struct _score_elf_section_data
133{
134 struct bfd_elf_section_data elf;
135 union
136 {
137 struct score_got_info *got_info;
138 bfd_byte *tdata;
139 }
140 u;
141};
142
143#define score_elf_section_data(sec) \
144 ((struct _score_elf_section_data *) elf_section_data (sec))
145
146/* The size of a symbol-table entry. */
147#define SCORE_ELF_SYM_SIZE(abfd) \
148 (get_elf_backend_data (abfd)->s->sizeof_sym)
149
150/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
151 from smaller values. Start with zero, widen, *then* decrement. */
152#define MINUS_ONE (((bfd_vma)0) - 1)
153#define MINUS_TWO (((bfd_vma)0) - 2)
154
155#define PDR_SIZE 32
156
157
158/* The number of local .got entries we reserve. */
159#define SCORE_RESERVED_GOTNO (2)
160#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
161
162/* The offset of $gp from the beginning of the .got section. */
163#define ELF_SCORE_GP_OFFSET(abfd) (0x3ff0)
164/* The maximum size of the GOT for it to be addressable using 15-bit offsets from $gp. */
165#define SCORE_ELF_GOT_MAX_SIZE(abfd) (ELF_SCORE_GP_OFFSET(abfd) + 0x3fff)
166
167#define SCORE_ELF_STUB_SECTION_NAME (".SCORE.stub")
168#define SCORE_FUNCTION_STUB_SIZE (16)
169
c3b7224a 170#define STUB_LW 0xc3bcc010 /* lw r29, [r28, -0x3ff0] */
1c0d3aa6
NC
171#define STUB_MOVE 0x8363bc56 /* mv r27, r3 */
172#define STUB_LI16 0x87548000 /* ori r26, .dynsym_index */
173#define STUB_BRL 0x801dbc09 /* brl r29 */
174
175#define SCORE_ELF_GOT_SIZE(abfd) \
176 (get_elf_backend_data (abfd)->s->arch_size / 8)
177
178#define SCORE_ELF_ADD_DYNAMIC_ENTRY(info, tag, val) \
07d6d2b8 179 (_bfd_elf_add_dynamic_entry (info, (bfd_vma) tag, (bfd_vma) val))
1c0d3aa6
NC
180
181/* The size of an external dynamic table entry. */
182#define SCORE_ELF_DYN_SIZE(abfd) \
183 (get_elf_backend_data (abfd)->s->sizeof_dyn)
184
185/* The size of an external REL relocation. */
186#define SCORE_ELF_REL_SIZE(abfd) \
187 (get_elf_backend_data (abfd)->s->sizeof_rel)
188
189/* The default alignment for sections, as a power of two. */
190#define SCORE_ELF_LOG_FILE_ALIGN(abfd)\
191 (get_elf_backend_data (abfd)->s->log_file_align)
192
1c0d3aa6
NC
193static bfd_byte *hi16_rel_addr;
194
195/* This will be used when we sort the dynamic relocation records. */
196static bfd *reldyn_sorting_bfd;
197
198/* SCORE ELF uses two common sections. One is the usual one, and the
199 other is for small objects. All the small objects are kept
200 together, and then referenced via the gp pointer, which yields
201 faster assembler code. This is what we use for the small common
202 section. This approach is copied from ecoff.c. */
203static asection score_elf_scom_section;
7f3a18cf
AM
204static const asymbol score_elf_scom_symbol =
205 GLOBAL_SYM_INIT (".scommon", &score_elf_scom_section);
206static asection score_elf_scom_section =
207 BFD_FAKE_SECTION (score_elf_scom_section, &score_elf_scom_symbol,
208 ".scommon", 0, SEC_IS_COMMON | SEC_SMALL_DATA);
1c0d3aa6 209
c3b7224a
NC
210static bfd_vma
211score_bfd_get_16 (bfd *abfd, const void *data)
212{
213 return bfd_get_16 (abfd, data);
214}
215
216static bfd_vma
217score3_bfd_getl32 (const void *p)
218{
219 const bfd_byte *addr = p;
220 unsigned long v;
221
222 v = (unsigned long) addr[2];
223 v |= (unsigned long) addr[3] << 8;
224 v |= (unsigned long) addr[0] << 16;
225 v |= (unsigned long) addr[1] << 24;
226 return v;
227}
228
229static bfd_vma
230score3_bfd_getl48 (const void *p)
231{
232 const bfd_byte *addr = p;
0e3c1eeb
AM
233 uint64_t v;
234
235 v = (uint64_t) addr[4];
236 v |= (uint64_t) addr[5] << 8;
237 v |= (uint64_t) addr[2] << 16;
238 v |= (uint64_t) addr[3] << 24;
239 v |= (uint64_t) addr[0] << 32;
240 v |= (uint64_t) addr[1] << 40;
c3b7224a
NC
241 return v;
242}
243
244static bfd_vma
245score_bfd_get_32 (bfd *abfd, const void *data)
246{
247 if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
248 return score3_bfd_getl32 (data);
249 else
250 return bfd_get_32 (abfd, data);
251}
252
253static bfd_vma
254score_bfd_get_48 (bfd *abfd, const void *p)
255{
256 if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
257 return score3_bfd_getl48 (p);
258 else
259 return bfd_get_bits (p, 48, 1);
260}
261
262static void
263score_bfd_put_16 (bfd *abfd, bfd_vma addr, void *data)
264{
265 return bfd_put_16 (abfd, addr, data);
266}
267
268static void
269score3_bfd_putl32 (bfd_vma data, void *p)
270{
271 bfd_byte *addr = p;
272 addr[0] = (data >> 16) & 0xff;
273 addr[1] = (data >> 24) & 0xff;
274 addr[2] = data & 0xff;
275 addr[3] = (data >> 8) & 0xff;
276}
277
278static void
279score3_bfd_putl48 (bfd_vma data, void *p)
280{
281 bfd_byte *addr = p;
282 addr[0] = (data >> 32) & 0xff;
283 addr[1] = (data >> 40) & 0xff;
284 addr[2] = (data >> 16) & 0xff;
285 addr[3] = (data >> 24) & 0xff;
286 addr[4] = data & 0xff;
287 addr[5] = (data >> 8) & 0xff;
288}
289
290static void
291score_bfd_put_32 (bfd *abfd, bfd_vma addr, void *data)
292{
293 if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
294 return score3_bfd_putl32 (addr, data);
295 else
296 return bfd_put_32 (abfd, addr, data);
297}
298
299static void
300score_bfd_put_48 (bfd *abfd, bfd_vma val, void *p)
301{
302 if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
303 return score3_bfd_putl48 (val, p);
304 else
305 return bfd_put_bits (val, p, 48, 1);
306}
307
1c0d3aa6
NC
308static bfd_reloc_status_type
309score_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED,
07d6d2b8
AM
310 arelent *reloc_entry,
311 asymbol *symbol ATTRIBUTE_UNUSED,
312 void * data,
313 asection *input_section ATTRIBUTE_UNUSED,
314 bfd *output_bfd ATTRIBUTE_UNUSED,
315 char **error_message ATTRIBUTE_UNUSED)
1c0d3aa6
NC
316{
317 hi16_rel_addr = (bfd_byte *) data + reloc_entry->address;
318 return bfd_reloc_ok;
319}
320
321static bfd_reloc_status_type
322score_elf_lo16_reloc (bfd *abfd,
07d6d2b8
AM
323 arelent *reloc_entry,
324 asymbol *symbol ATTRIBUTE_UNUSED,
325 void * data,
326 asection *input_section,
327 bfd *output_bfd ATTRIBUTE_UNUSED,
328 char **error_message ATTRIBUTE_UNUSED)
1c0d3aa6
NC
329{
330 bfd_vma addend = 0, offset = 0;
331 unsigned long val;
332 unsigned long hi16_offset, hi16_value, uvalue;
333
c3b7224a 334 hi16_value = score_bfd_get_32 (abfd, hi16_rel_addr);
1c0d3aa6 335 hi16_offset = ((((hi16_value >> 16) & 0x3) << 15) | (hi16_value & 0x7fff)) >> 1;
c3b7224a 336 addend = score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
1c0d3aa6
NC
337 offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1;
338 val = reloc_entry->addend;
339 if (reloc_entry->address > input_section->size)
340 return bfd_reloc_outofrange;
341 uvalue = ((hi16_offset << 16) | (offset & 0xffff)) + val;
342 hi16_offset = (uvalue >> 16) << 1;
343 hi16_value = (hi16_value & ~0x37fff) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
c3b7224a 344 score_bfd_put_32 (abfd, hi16_value, hi16_rel_addr);
1c0d3aa6
NC
345 offset = (uvalue & 0xffff) << 1;
346 addend = (addend & ~0x37fff) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
c3b7224a 347 score_bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address);
1c0d3aa6
NC
348 return bfd_reloc_ok;
349}
350
351/* Set the GP value for OUTPUT_BFD. Returns FALSE if this is a
352 dangerous relocation. */
353
0a1b45a2 354static bool
1c0d3aa6
NC
355score_elf_assign_gp (bfd *output_bfd, bfd_vma *pgp)
356{
357 unsigned int count;
358 asymbol **sym;
359 unsigned int i;
360
361 /* If we've already figured out what GP will be, just return it. */
362 *pgp = _bfd_get_gp_value (output_bfd);
363 if (*pgp)
0a1b45a2 364 return true;
1c0d3aa6
NC
365
366 count = bfd_get_symcount (output_bfd);
367 sym = bfd_get_outsymbols (output_bfd);
368
369 /* The linker script will have created a symbol named `_gp' with the
370 appropriate value. */
371 if (sym == NULL)
372 i = count;
373 else
374 {
375 for (i = 0; i < count; i++, sym++)
07d6d2b8
AM
376 {
377 const char *name;
378
379 name = bfd_asymbol_name (*sym);
380 if (*name == '_' && strcmp (name, "_gp") == 0)
381 {
382 *pgp = bfd_asymbol_value (*sym);
383 _bfd_set_gp_value (output_bfd, *pgp);
384 break;
385 }
386 }
1c0d3aa6
NC
387 }
388
389 if (i >= count)
390 {
391 /* Only get the error once. */
392 *pgp = 4;
393 _bfd_set_gp_value (output_bfd, *pgp);
0a1b45a2 394 return false;
1c0d3aa6
NC
395 }
396
0a1b45a2 397 return true;
1c0d3aa6
NC
398}
399
400/* We have to figure out the gp value, so that we can adjust the
401 symbol value correctly. We look up the symbol _gp in the output
402 BFD. If we can't find it, we're stuck. We cache it in the ELF
403 target data. We don't need to adjust the symbol value for an
404 external symbol if we are producing relocatable output. */
1c0d3aa6
NC
405static bfd_reloc_status_type
406score_elf_final_gp (bfd *output_bfd,
07d6d2b8 407 asymbol *symbol,
0a1b45a2 408 bool relocatable,
07d6d2b8
AM
409 char **error_message,
410 bfd_vma *pgp)
1c0d3aa6
NC
411{
412 if (bfd_is_und_section (symbol->section)
413 && ! relocatable)
414 {
415 *pgp = 0;
416 return bfd_reloc_undefined;
417 }
418
419 *pgp = _bfd_get_gp_value (output_bfd);
420 if (*pgp == 0
421 && (! relocatable
07d6d2b8 422 || (symbol->flags & BSF_SECTION_SYM) != 0))
1c0d3aa6
NC
423 {
424 if (relocatable)
07d6d2b8
AM
425 {
426 /* Make up a value. */
427 *pgp = symbol->section->output_section->vma + 0x4000;
428 _bfd_set_gp_value (output_bfd, *pgp);
429 }
1c0d3aa6 430 else if (!score_elf_assign_gp (output_bfd, pgp))
07d6d2b8
AM
431 {
432 *error_message =
433 (char *) _("GP relative relocation when _gp not defined");
434 return bfd_reloc_dangerous;
435 }
1c0d3aa6
NC
436 }
437
438 return bfd_reloc_ok;
439}
440
441static bfd_reloc_status_type
442score_elf_gprel15_with_gp (bfd *abfd,
07d6d2b8
AM
443 arelent *reloc_entry,
444 asection *input_section,
0a1b45a2 445 bool relocateable,
07d6d2b8
AM
446 void * data,
447 bfd_vma gp ATTRIBUTE_UNUSED)
1c0d3aa6 448{
1c0d3aa6
NC
449 unsigned long insn;
450
1c0d3aa6
NC
451 if (reloc_entry->address > input_section->size)
452 return bfd_reloc_outofrange;
453
c3b7224a 454 insn = score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
1c0d3aa6
NC
455 if (((reloc_entry->addend & 0xffffc000) != 0)
456 && ((reloc_entry->addend & 0xffffc000) != 0xffffc000))
457 return bfd_reloc_overflow;
458
459 insn = (insn & ~0x7fff) | (reloc_entry->addend & 0x7fff);
c3b7224a 460 score_bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
1c0d3aa6
NC
461 if (relocateable)
462 reloc_entry->address += input_section->output_offset;
463
464 return bfd_reloc_ok;
465}
466
467static bfd_reloc_status_type
468gprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry,
0a1b45a2 469 asection *input_section, bool relocatable,
07d6d2b8 470 void *data, bfd_vma gp)
1c0d3aa6
NC
471{
472 bfd_vma relocation;
473 bfd_vma val;
474
475 if (bfd_is_com_section (symbol->section))
476 relocation = 0;
477 else
478 relocation = symbol->value;
479
480 relocation += symbol->section->output_section->vma;
481 relocation += symbol->section->output_offset;
482
483 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
484 return bfd_reloc_outofrange;
485
486 /* Set val to the offset into the section or symbol. */
487 val = reloc_entry->addend;
488
489 if (reloc_entry->howto->partial_inplace)
c3b7224a 490 val += score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
1c0d3aa6
NC
491
492 /* Adjust val for the final section location and GP value. If we
493 are producing relocatable output, we don't want to do this for
494 an external symbol. */
495 if (! relocatable
496 || (symbol->flags & BSF_SECTION_SYM) != 0)
497 val += relocation - gp;
498
499 if (reloc_entry->howto->partial_inplace)
c3b7224a 500 score_bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
1c0d3aa6
NC
501 else
502 reloc_entry->addend = val;
503
504 if (relocatable)
505 reloc_entry->address += input_section->output_offset;
506
507 return bfd_reloc_ok;
508}
509
510static bfd_reloc_status_type
511score_elf_gprel15_reloc (bfd *abfd,
07d6d2b8
AM
512 arelent *reloc_entry,
513 asymbol *symbol,
514 void * data,
515 asection *input_section,
516 bfd *output_bfd,
517 char **error_message)
1c0d3aa6 518{
0a1b45a2 519 bool relocateable;
1c0d3aa6
NC
520 bfd_reloc_status_type ret;
521 bfd_vma gp;
522
c3b7224a 523 if (output_bfd != NULL
1c0d3aa6
NC
524 && (symbol->flags & BSF_SECTION_SYM) == 0 && reloc_entry->addend == 0)
525 {
526 reloc_entry->address += input_section->output_offset;
527 return bfd_reloc_ok;
528 }
c3b7224a 529 if (output_bfd != NULL)
0a1b45a2 530 relocateable = true;
1c0d3aa6
NC
531 else
532 {
0a1b45a2 533 relocateable = false;
1c0d3aa6
NC
534 output_bfd = symbol->section->output_section->owner;
535 }
536
537 ret = score_elf_final_gp (output_bfd, symbol, relocateable, error_message, &gp);
538 if (ret != bfd_reloc_ok)
539 return ret;
540
9bc8e54b
SM
541 return score_elf_gprel15_with_gp (abfd, reloc_entry,
542 input_section, relocateable, data, gp);
1c0d3aa6
NC
543}
544
545/* Do a R_SCORE_GPREL32 relocation. This is a 32 bit value which must
546 become the offset from the gp register. */
547
548static bfd_reloc_status_type
549score_elf_gprel32_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
07d6d2b8
AM
550 void *data, asection *input_section, bfd *output_bfd,
551 char **error_message)
1c0d3aa6 552{
0a1b45a2 553 bool relocatable;
1c0d3aa6
NC
554 bfd_reloc_status_type ret;
555 bfd_vma gp;
556
557 /* R_SCORE_GPREL32 relocations are defined for local symbols only. */
558 if (output_bfd != NULL
559 && (symbol->flags & BSF_SECTION_SYM) == 0
560 && (symbol->flags & BSF_LOCAL) != 0)
561 {
562 *error_message = (char *)
07d6d2b8 563 _("32bits gp relative relocation occurs for an external symbol");
1c0d3aa6
NC
564 return bfd_reloc_outofrange;
565 }
566
567 if (output_bfd != NULL)
0a1b45a2 568 relocatable = true;
1c0d3aa6
NC
569 else
570 {
0a1b45a2 571 relocatable = false;
1c0d3aa6
NC
572 output_bfd = symbol->section->output_section->owner;
573 }
574
575 ret = score_elf_final_gp (output_bfd, symbol, relocatable, error_message, &gp);
576 if (ret != bfd_reloc_ok)
577 return ret;
578
c3b7224a 579 gp = 0;
1c0d3aa6 580 return gprel32_with_gp (abfd, symbol, reloc_entry, input_section,
07d6d2b8 581 relocatable, data, gp);
1c0d3aa6
NC
582}
583
584/* A howto special_function for R_SCORE_GOT15 relocations. This is just
585 like any other 16-bit relocation when applied to global symbols, but is
586 treated in the same as R_SCORE_HI16 when applied to local symbols. */
1c0d3aa6
NC
587static bfd_reloc_status_type
588score_elf_got15_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
07d6d2b8
AM
589 void *data, asection *input_section,
590 bfd *output_bfd, char **error_message)
1c0d3aa6
NC
591{
592 if ((symbol->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
e6f7f6d1
AM
593 || bfd_is_und_section (bfd_asymbol_section (symbol))
594 || bfd_is_com_section (bfd_asymbol_section (symbol)))
1c0d3aa6
NC
595 /* The relocation is against a global symbol. */
596 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
07d6d2b8
AM
597 input_section, output_bfd,
598 error_message);
1c0d3aa6
NC
599
600 return score_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
07d6d2b8 601 input_section, output_bfd, error_message);
1c0d3aa6
NC
602}
603
604static bfd_reloc_status_type
605score_elf_got_lo16_reloc (bfd *abfd,
07d6d2b8
AM
606 arelent *reloc_entry,
607 asymbol *symbol ATTRIBUTE_UNUSED,
608 void * data,
609 asection *input_section,
610 bfd *output_bfd ATTRIBUTE_UNUSED,
611 char **error_message ATTRIBUTE_UNUSED)
1c0d3aa6
NC
612{
613 bfd_vma addend = 0, offset = 0;
0150d082
ML
614 signed long val;
615 signed long hi16_offset, hi16_value, uvalue;
1c0d3aa6 616
c3b7224a 617 hi16_value = score_bfd_get_32 (abfd, hi16_rel_addr);
1c0d3aa6 618 hi16_offset = ((((hi16_value >> 16) & 0x3) << 15) | (hi16_value & 0x7fff)) >> 1;
c3b7224a 619 addend = score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
1c0d3aa6
NC
620 offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1;
621 val = reloc_entry->addend;
622 if (reloc_entry->address > input_section->size)
623 return bfd_reloc_outofrange;
624 uvalue = ((hi16_offset << 16) | (offset & 0xffff)) + val;
0150d082
ML
625 if ((uvalue > -0x8000) && (uvalue < 0x7fff))
626 hi16_offset = 0;
627 else
628 hi16_offset = (uvalue >> 16) & 0x7fff;
1c0d3aa6 629 hi16_value = (hi16_value & ~0x37fff) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
c3b7224a 630 score_bfd_put_32 (abfd, hi16_value, hi16_rel_addr);
1c0d3aa6
NC
631 offset = (uvalue & 0xffff) << 1;
632 addend = (addend & ~0x37fff) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
c3b7224a 633 score_bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address);
1c0d3aa6
NC
634 return bfd_reloc_ok;
635}
636
637static reloc_howto_type elf32_score_howto_table[] =
638{
639 /* No relocation. */
07d6d2b8
AM
640 HOWTO (R_SCORE_NONE, /* type */
641 0, /* rightshift */
c94cb026 642 0, /* size */
07d6d2b8 643 0, /* bitsize */
0a1b45a2 644 false, /* pc_relative */
07d6d2b8
AM
645 0, /* bitpos */
646 complain_overflow_dont,/* complain_on_overflow */
647 bfd_elf_generic_reloc, /* special_function */
648 "R_SCORE_NONE", /* name */
0a1b45a2 649 false, /* partial_inplace */
07d6d2b8
AM
650 0, /* src_mask */
651 0, /* dst_mask */
0a1b45a2 652 false), /* pcrel_offset */
1c0d3aa6
NC
653
654 /* R_SCORE_HI16 */
07d6d2b8
AM
655 HOWTO (R_SCORE_HI16, /* type */
656 0, /* rightshift */
c94cb026 657 4, /* size */
07d6d2b8 658 16, /* bitsize */
0a1b45a2 659 false, /* pc_relative */
07d6d2b8
AM
660 1, /* bitpos */
661 complain_overflow_dont,/* complain_on_overflow */
662 score_elf_hi16_reloc, /* special_function */
663 "R_SCORE_HI16", /* name */
0a1b45a2 664 true, /* partial_inplace */
07d6d2b8
AM
665 0x37fff, /* src_mask */
666 0x37fff, /* dst_mask */
0a1b45a2 667 false), /* pcrel_offset */
1c0d3aa6
NC
668
669 /* R_SCORE_LO16 */
07d6d2b8
AM
670 HOWTO (R_SCORE_LO16, /* type */
671 0, /* rightshift */
c94cb026 672 4, /* size */
07d6d2b8 673 16, /* bitsize */
0a1b45a2 674 false, /* pc_relative */
07d6d2b8
AM
675 1, /* bitpos */
676 complain_overflow_dont,/* complain_on_overflow */
677 score_elf_lo16_reloc, /* special_function */
678 "R_SCORE_LO16", /* name */
0a1b45a2 679 true, /* partial_inplace */
07d6d2b8
AM
680 0x37fff, /* src_mask */
681 0x37fff, /* dst_mask */
0a1b45a2 682 false), /* pcrel_offset */
1c0d3aa6 683
c3b7224a 684 /* R_SCORE_BCMP */
07d6d2b8
AM
685 HOWTO (R_SCORE_BCMP, /* type */
686 1, /* rightshift */
c94cb026 687 4, /* size */
07d6d2b8 688 16, /* bitsize */
0a1b45a2 689 true, /* pc_relative */
07d6d2b8
AM
690 1, /* bitpos */
691 complain_overflow_dont,/* complain_on_overflow */
692 bfd_elf_generic_reloc, /* special_function */
693 "R_SCORE_BCMP", /* name */
0a1b45a2 694 false, /* partial_inplace */
07d6d2b8
AM
695 0x03e00381, /* src_mask */
696 0x03e00381, /* dst_mask */
0a1b45a2 697 false), /* pcrel_offset */
1c0d3aa6
NC
698
699 /*R_SCORE_24 */
07d6d2b8
AM
700 HOWTO (R_SCORE_24, /* type */
701 1, /* rightshift */
c94cb026 702 4, /* size */
07d6d2b8 703 24, /* bitsize */
0a1b45a2 704 false, /* pc_relative */
07d6d2b8
AM
705 1, /* bitpos */
706 complain_overflow_dont,/* complain_on_overflow */
707 bfd_elf_generic_reloc, /* special_function */
708 "R_SCORE_24", /* name */
0a1b45a2 709 false, /* partial_inplace */
07d6d2b8
AM
710 0x3ff7fff, /* src_mask */
711 0x3ff7fff, /* dst_mask */
0a1b45a2 712 false), /* pcrel_offset */
1c0d3aa6
NC
713
714 /*R_SCORE_PC19 */
07d6d2b8
AM
715 HOWTO (R_SCORE_PC19, /* type */
716 1, /* rightshift */
c94cb026 717 4, /* size */
07d6d2b8 718 19, /* bitsize */
0a1b45a2 719 true, /* pc_relative */
07d6d2b8
AM
720 1, /* bitpos */
721 complain_overflow_dont,/* complain_on_overflow */
722 bfd_elf_generic_reloc, /* special_function */
723 "R_SCORE_PC19", /* name */
0a1b45a2 724 false, /* partial_inplace */
07d6d2b8
AM
725 0x3ff03fe, /* src_mask */
726 0x3ff03fe, /* dst_mask */
0a1b45a2 727 false), /* pcrel_offset */
1c0d3aa6
NC
728
729 /*R_SCORE16_11 */
07d6d2b8
AM
730 HOWTO (R_SCORE16_11, /* type */
731 1, /* rightshift */
c94cb026 732 2, /* size */
07d6d2b8 733 11, /* bitsize */
0a1b45a2 734 false, /* pc_relative */
07d6d2b8
AM
735 1, /* bitpos */
736 complain_overflow_dont,/* complain_on_overflow */
737 bfd_elf_generic_reloc, /* special_function */
738 "R_SCORE16_11", /* name */
0a1b45a2 739 false, /* partial_inplace */
07d6d2b8
AM
740 0x000000ffe, /* src_mask */
741 0x000000ffe, /* dst_mask */
0a1b45a2 742 false), /* pcrel_offset */
1c0d3aa6
NC
743
744 /* R_SCORE16_PC8 */
07d6d2b8
AM
745 HOWTO (R_SCORE16_PC8, /* type */
746 1, /* rightshift */
c94cb026 747 2, /* size */
07d6d2b8 748 9, /* bitsize */
0a1b45a2 749 true, /* pc_relative */
07d6d2b8
AM
750 0, /* bitpos */
751 complain_overflow_dont,/* complain_on_overflow */
752 bfd_elf_generic_reloc, /* special_function */
753 "R_SCORE16_PC8", /* name */
0a1b45a2 754 false, /* partial_inplace */
07d6d2b8
AM
755 0x000001ff, /* src_mask */
756 0x000001ff, /* dst_mask */
0a1b45a2 757 false), /* pcrel_offset */
1c0d3aa6
NC
758
759 /* 32 bit absolute */
07d6d2b8
AM
760 HOWTO (R_SCORE_ABS32, /* type 8 */
761 0, /* rightshift */
c94cb026 762 4, /* size */
07d6d2b8 763 32, /* bitsize */
0a1b45a2 764 false, /* pc_relative */
07d6d2b8
AM
765 0, /* bitpos */
766 complain_overflow_bitfield, /* complain_on_overflow */
767 bfd_elf_generic_reloc, /* special_function */
768 "R_SCORE_ABS32", /* name */
0a1b45a2 769 false, /* partial_inplace */
07d6d2b8
AM
770 0xffffffff, /* src_mask */
771 0xffffffff, /* dst_mask */
0a1b45a2 772 false), /* pcrel_offset */
1c0d3aa6
NC
773
774 /* 16 bit absolute */
07d6d2b8
AM
775 HOWTO (R_SCORE_ABS16, /* type 11 */
776 0, /* rightshift */
c94cb026 777 2, /* size */
07d6d2b8 778 16, /* bitsize */
0a1b45a2 779 false, /* pc_relative */
07d6d2b8
AM
780 0, /* bitpos */
781 complain_overflow_bitfield, /* complain_on_overflow */
782 bfd_elf_generic_reloc, /* special_function */
783 "R_SCORE_ABS16", /* name */
0a1b45a2 784 false, /* partial_inplace */
07d6d2b8
AM
785 0x0000ffff, /* src_mask */
786 0x0000ffff, /* dst_mask */
0a1b45a2 787 false), /* pcrel_offset */
1c0d3aa6
NC
788
789 /* R_SCORE_DUMMY2 */
07d6d2b8
AM
790 HOWTO (R_SCORE_DUMMY2, /* type */
791 0, /* rightshift */
c94cb026 792 4, /* size */
07d6d2b8 793 16, /* bitsize */
0a1b45a2 794 false, /* pc_relative */
07d6d2b8
AM
795 0, /* bitpos */
796 complain_overflow_dont,/* complain_on_overflow */
797 bfd_elf_generic_reloc, /* special_function */
798 "R_SCORE_DUMMY2", /* name */
0a1b45a2 799 true, /* partial_inplace */
07d6d2b8
AM
800 0x00007fff, /* src_mask */
801 0x00007fff, /* dst_mask */
0a1b45a2 802 false), /* pcrel_offset */
1c0d3aa6
NC
803
804 /* R_SCORE_GP15 */
07d6d2b8
AM
805 HOWTO (R_SCORE_GP15, /* type */
806 0, /* rightshift */
c94cb026 807 4, /* size */
07d6d2b8 808 16, /* bitsize */
0a1b45a2 809 false, /* pc_relative */
07d6d2b8
AM
810 0, /* bitpos */
811 complain_overflow_dont,/* complain_on_overflow */
812 score_elf_gprel15_reloc,/* special_function */
813 "R_SCORE_GP15", /* name */
0a1b45a2 814 true, /* partial_inplace */
07d6d2b8
AM
815 0x00007fff, /* src_mask */
816 0x00007fff, /* dst_mask */
0a1b45a2 817 false), /* pcrel_offset */
1c0d3aa6
NC
818
819 /* GNU extension to record C++ vtable hierarchy. */
820 HOWTO (R_SCORE_GNU_VTINHERIT, /* type */
07d6d2b8 821 0, /* rightshift */
c94cb026 822 4, /* size */
07d6d2b8 823 0, /* bitsize */
0a1b45a2 824 false, /* pc_relative */
07d6d2b8
AM
825 0, /* bitpos */
826 complain_overflow_dont,/* complain_on_overflow */
827 NULL, /* special_function */
828 "R_SCORE_GNU_VTINHERIT", /* name */
0a1b45a2 829 false, /* partial_inplace */
07d6d2b8
AM
830 0, /* src_mask */
831 0, /* dst_mask */
0a1b45a2 832 false), /* pcrel_offset */
1c0d3aa6
NC
833
834 /* GNU extension to record C++ vtable member usage */
07d6d2b8
AM
835 HOWTO (R_SCORE_GNU_VTENTRY, /* type */
836 0, /* rightshift */
c94cb026 837 4, /* size */
07d6d2b8 838 0, /* bitsize */
0a1b45a2 839 false, /* pc_relative */
07d6d2b8
AM
840 0, /* bitpos */
841 complain_overflow_dont,/* complain_on_overflow */
842 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
843 "R_SCORE_GNU_VTENTRY", /* name */
0a1b45a2 844 false, /* partial_inplace */
07d6d2b8
AM
845 0, /* src_mask */
846 0, /* dst_mask */
0a1b45a2 847 false), /* pcrel_offset */
1c0d3aa6
NC
848
849 /* Reference to global offset table. */
07d6d2b8
AM
850 HOWTO (R_SCORE_GOT15, /* type */
851 0, /* rightshift */
c94cb026 852 4, /* size */
07d6d2b8 853 16, /* bitsize */
0a1b45a2 854 false, /* pc_relative */
07d6d2b8
AM
855 0, /* bitpos */
856 complain_overflow_signed, /* complain_on_overflow */
857 score_elf_got15_reloc, /* special_function */
858 "R_SCORE_GOT15", /* name */
0a1b45a2 859 true, /* partial_inplace */
07d6d2b8
AM
860 0x00007fff, /* src_mask */
861 0x00007fff, /* dst_mask */
0a1b45a2 862 false), /* pcrel_offset */
1c0d3aa6
NC
863
864 /* Low 16 bits of displacement in global offset table. */
07d6d2b8
AM
865 HOWTO (R_SCORE_GOT_LO16, /* type */
866 0, /* rightshift */
c94cb026 867 4, /* size */
07d6d2b8 868 16, /* bitsize */
0a1b45a2 869 false, /* pc_relative */
07d6d2b8
AM
870 1, /* bitpos */
871 complain_overflow_dont,/* complain_on_overflow */
872 score_elf_got_lo16_reloc, /* special_function */
873 "R_SCORE_GOT_LO16", /* name */
0a1b45a2 874 true, /* partial_inplace */
07d6d2b8
AM
875 0x37ffe, /* src_mask */
876 0x37ffe, /* dst_mask */
0a1b45a2 877 false), /* pcrel_offset */
1c0d3aa6
NC
878
879 /* 15 bit call through global offset table. */
07d6d2b8
AM
880 HOWTO (R_SCORE_CALL15, /* type */
881 0, /* rightshift */
c94cb026 882 4, /* size */
07d6d2b8 883 16, /* bitsize */
0a1b45a2 884 false, /* pc_relative */
07d6d2b8
AM
885 0, /* bitpos */
886 complain_overflow_signed, /* complain_on_overflow */
887 bfd_elf_generic_reloc, /* special_function */
888 "R_SCORE_CALL15", /* name */
0a1b45a2 889 true, /* partial_inplace */
07d6d2b8
AM
890 0x0000ffff, /* src_mask */
891 0x0000ffff, /* dst_mask */
0a1b45a2 892 false), /* pcrel_offset */
1c0d3aa6
NC
893
894 /* 32 bit GP relative reference. */
07d6d2b8
AM
895 HOWTO (R_SCORE_GPREL32, /* type */
896 0, /* rightshift */
c94cb026 897 4, /* size */
07d6d2b8 898 32, /* bitsize */
0a1b45a2 899 false, /* pc_relative */
07d6d2b8
AM
900 0, /* bitpos */
901 complain_overflow_dont,/* complain_on_overflow */
902 score_elf_gprel32_reloc, /* special_function */
903 "R_SCORE_GPREL32", /* name */
0a1b45a2 904 true, /* partial_inplace */
07d6d2b8
AM
905 0xffffffff, /* src_mask */
906 0xffffffff, /* dst_mask */
0a1b45a2 907 false), /* pcrel_offset */
1c0d3aa6
NC
908
909 /* 32 bit symbol relative relocation. */
07d6d2b8
AM
910 HOWTO (R_SCORE_REL32, /* type */
911 0, /* rightshift */
c94cb026 912 4, /* size */
07d6d2b8 913 32, /* bitsize */
0a1b45a2 914 false, /* pc_relative */
07d6d2b8
AM
915 0, /* bitpos */
916 complain_overflow_dont,/* complain_on_overflow */
917 bfd_elf_generic_reloc, /* special_function */
918 "R_SCORE_REL32", /* name */
0a1b45a2 919 true, /* partial_inplace */
07d6d2b8
AM
920 0xffffffff, /* src_mask */
921 0xffffffff, /* dst_mask */
0a1b45a2 922 false), /* pcrel_offset */
1c0d3aa6
NC
923
924 /* R_SCORE_DUMMY_HI16 */
07d6d2b8
AM
925 HOWTO (R_SCORE_DUMMY_HI16, /* type */
926 0, /* rightshift */
c94cb026 927 4, /* size */
07d6d2b8 928 16, /* bitsize */
0a1b45a2 929 false, /* pc_relative */
07d6d2b8
AM
930 1, /* bitpos */
931 complain_overflow_dont,/* complain_on_overflow */
932 score_elf_hi16_reloc, /* special_function */
933 "R_SCORE_DUMMY_HI16", /* name */
0a1b45a2 934 true, /* partial_inplace */
07d6d2b8
AM
935 0x37fff, /* src_mask */
936 0x37fff, /* dst_mask */
0a1b45a2 937 false), /* pcrel_offset */
c3b7224a
NC
938
939 /* R_SCORE_IMM30 */
07d6d2b8
AM
940 HOWTO (R_SCORE_IMM30, /* type */
941 2, /* rightshift */
c94cb026 942 4, /* size */
07d6d2b8 943 30, /* bitsize */
0a1b45a2 944 false, /* pc_relative */
07d6d2b8
AM
945 7, /* bitpos */
946 complain_overflow_dont,/* complain_on_overflow */
947 bfd_elf_generic_reloc, /* special_function */
948 "R_SCORE_IMM30", /* name */
0a1b45a2 949 false, /* partial_inplace */
07d6d2b8
AM
950 0x7f7fff7f80LL, /* src_mask */
951 0x7f7fff7f80LL, /* dst_mask */
0a1b45a2 952 false), /* pcrel_offset */
c3b7224a
NC
953
954 /* R_SCORE_IMM32 */
07d6d2b8
AM
955 HOWTO (R_SCORE_IMM32, /* type */
956 0, /* rightshift */
c94cb026 957 4, /* size */
07d6d2b8 958 32, /* bitsize */
0a1b45a2 959 false, /* pc_relative */
07d6d2b8
AM
960 5, /* bitpos */
961 complain_overflow_dont,/* complain_on_overflow */
962 bfd_elf_generic_reloc, /* special_function */
963 "R_SCORE_IMM32", /* name */
0a1b45a2 964 false, /* partial_inplace */
07d6d2b8
AM
965 0x7f7fff7fe0LL, /* src_mask */
966 0x7f7fff7fe0LL, /* dst_mask */
0a1b45a2 967 false), /* pcrel_offset */
1c0d3aa6
NC
968};
969
970struct score_reloc_map
971{
972 bfd_reloc_code_real_type bfd_reloc_val;
973 unsigned char elf_reloc_val;
974};
975
976static const struct score_reloc_map elf32_score_reloc_map[] =
977{
07d6d2b8
AM
978 {BFD_RELOC_NONE, R_SCORE_NONE},
979 {BFD_RELOC_HI16_S, R_SCORE_HI16},
980 {BFD_RELOC_LO16, R_SCORE_LO16},
981 {BFD_RELOC_SCORE_BCMP, R_SCORE_BCMP},
982 {BFD_RELOC_SCORE_JMP, R_SCORE_24},
983 {BFD_RELOC_SCORE_BRANCH, R_SCORE_PC19},
984 {BFD_RELOC_SCORE16_JMP, R_SCORE16_11},
985 {BFD_RELOC_SCORE16_BRANCH, R_SCORE16_PC8},
986 {BFD_RELOC_32, R_SCORE_ABS32},
987 {BFD_RELOC_16, R_SCORE_ABS16},
988 {BFD_RELOC_SCORE_DUMMY2, R_SCORE_DUMMY2},
989 {BFD_RELOC_SCORE_GPREL15, R_SCORE_GP15},
990 {BFD_RELOC_VTABLE_INHERIT, R_SCORE_GNU_VTINHERIT},
991 {BFD_RELOC_VTABLE_ENTRY, R_SCORE_GNU_VTENTRY},
992 {BFD_RELOC_SCORE_GOT15, R_SCORE_GOT15},
993 {BFD_RELOC_SCORE_GOT_LO16, R_SCORE_GOT_LO16},
994 {BFD_RELOC_SCORE_CALL15, R_SCORE_CALL15},
995 {BFD_RELOC_GPREL32, R_SCORE_GPREL32},
996 {BFD_RELOC_32_PCREL, R_SCORE_REL32},
997 {BFD_RELOC_SCORE_DUMMY_HI16, R_SCORE_DUMMY_HI16},
998 {BFD_RELOC_SCORE_IMM30, R_SCORE_IMM30},
999 {BFD_RELOC_SCORE_IMM32, R_SCORE_IMM32},
1c0d3aa6
NC
1000};
1001
1002/* got_entries only match if they're identical, except for gotidx, so
1003 use all fields to compute the hash, and compare the appropriate
1004 union members. */
1c0d3aa6
NC
1005static hashval_t
1006score_elf_got_entry_hash (const void *entry_)
1007{
1008 const struct score_got_entry *entry = (struct score_got_entry *)entry_;
1009
1010 return entry->symndx
1011 + (!entry->abfd ? entry->d.address : entry->abfd->id);
1012}
1013
1014static int
1015score_elf_got_entry_eq (const void *entry1, const void *entry2)
1016{
1017 const struct score_got_entry *e1 = (struct score_got_entry *)entry1;
1018 const struct score_got_entry *e2 = (struct score_got_entry *)entry2;
1019
1020 return e1->abfd == e2->abfd && e1->symndx == e2->symndx
1021 && (! e1->abfd ? e1->d.address == e2->d.address
07d6d2b8
AM
1022 : e1->symndx >= 0 ? e1->d.addend == e2->d.addend
1023 : e1->d.h == e2->d.h);
1c0d3aa6
NC
1024}
1025
1026/* If H needs a GOT entry, assign it the highest available dynamic
1027 index. Otherwise, assign it the lowest available dynamic
1028 index. */
0a1b45a2 1029static bool
1c0d3aa6
NC
1030score_elf_sort_hash_table_f (struct score_elf_link_hash_entry *h, void *data)
1031{
1032 struct score_elf_hash_sort_data *hsd = data;
1033
1c0d3aa6
NC
1034 /* Symbols without dynamic symbol table entries aren't interesting at all. */
1035 if (h->root.dynindx == -1)
0a1b45a2 1036 return true;
1c0d3aa6
NC
1037
1038 /* Global symbols that need GOT entries that are not explicitly
1039 referenced are marked with got offset 2. Those that are
1040 referenced get a 1, and those that don't need GOT entries get
1041 -1. */
1042 if (h->root.got.offset == 2)
1043 {
1044 if (hsd->max_unref_got_dynindx == hsd->min_got_dynindx)
07d6d2b8 1045 hsd->low = (struct elf_link_hash_entry *) h;
1c0d3aa6
NC
1046 h->root.dynindx = hsd->max_unref_got_dynindx++;
1047 }
1048 else if (h->root.got.offset != 1)
1049 h->root.dynindx = hsd->max_non_got_dynindx++;
1050 else
1051 {
1052 h->root.dynindx = --hsd->min_got_dynindx;
1053 hsd->low = (struct elf_link_hash_entry *) h;
1054 }
1055
0a1b45a2 1056 return true;
1c0d3aa6
NC
1057}
1058
1059static asection *
0a1b45a2 1060score_elf_got_section (bfd *abfd, bool maybe_excluded)
1c0d3aa6 1061{
3d4d4302 1062 asection *sgot = bfd_get_linker_section (abfd, ".got");
1c0d3aa6
NC
1063
1064 if (sgot == NULL || (! maybe_excluded && (sgot->flags & SEC_EXCLUDE) != 0))
1065 return NULL;
1066 return sgot;
1067}
1068
1069/* Returns the GOT information associated with the link indicated by
1070 INFO. If SGOTP is non-NULL, it is filled in with the GOT section. */
1c0d3aa6
NC
1071static struct score_got_info *
1072score_elf_got_info (bfd *abfd, asection **sgotp)
1073{
1074 asection *sgot;
1075 struct score_got_info *g;
1076
0a1b45a2 1077 sgot = score_elf_got_section (abfd, true);
1c0d3aa6
NC
1078 BFD_ASSERT (sgot != NULL);
1079 BFD_ASSERT (elf_section_data (sgot) != NULL);
1080 g = score_elf_section_data (sgot)->u.got_info;
1081 BFD_ASSERT (g != NULL);
1082
1083 if (sgotp)
1084 *sgotp = sgot;
1085 return g;
1086}
1087
1088/* Sort the dynamic symbol table so that symbols that need GOT entries
1089 appear towards the end. This reduces the amount of GOT space
1090 required. MAX_LOCAL is used to set the number of local symbols
1091 known to be in the dynamic symbol table. During
af969b14 1092 s3_bfd_score_elf_late_size_sections, this value is 1. Afterward, the
1c0d3aa6 1093 section symbols are added and the count is higher. */
0a1b45a2 1094static bool
1c0d3aa6 1095score_elf_sort_hash_table (struct bfd_link_info *info,
07d6d2b8 1096 unsigned long max_local)
1c0d3aa6
NC
1097{
1098 struct score_elf_hash_sort_data hsd;
1099 struct score_got_info *g;
1100 bfd *dynobj;
1101
1102 dynobj = elf_hash_table (info)->dynobj;
1103
1104 g = score_elf_got_info (dynobj, NULL);
1105
1106 hsd.low = NULL;
1107 hsd.max_unref_got_dynindx =
1108 hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount
1109 /* In the multi-got case, assigned_gotno of the master got_info
1110 indicate the number of entries that aren't referenced in the
1111 primary GOT, but that must have entries because there are
1112 dynamic relocations that reference it. Since they aren't
1113 referenced, we move them to the end of the GOT, so that they
1114 don't prevent other entries that are referenced from getting
1115 too large offsets. */
1116 - (g->next ? g->assigned_gotno : 0);
1117 hsd.max_non_got_dynindx = max_local;
4dfe6ac6
NC
1118 score_elf_link_hash_traverse (elf_hash_table (info),
1119 score_elf_sort_hash_table_f,
1120 &hsd);
1c0d3aa6
NC
1121
1122 /* There should have been enough room in the symbol table to
1123 accommodate both the GOT and non-GOT symbols. */
1124 BFD_ASSERT (hsd.max_non_got_dynindx <= hsd.min_got_dynindx);
1125 BFD_ASSERT ((unsigned long)hsd.max_unref_got_dynindx
07d6d2b8 1126 <= elf_hash_table (info)->dynsymcount);
1c0d3aa6
NC
1127
1128 /* Now we know which dynamic symbol has the lowest dynamic symbol
1129 table index in the GOT. */
1130 g->global_gotsym = hsd.low;
1131
0a1b45a2 1132 return true;
1c0d3aa6
NC
1133}
1134
1135/* Create an entry in an score ELF linker hash table. */
4dfe6ac6 1136
1c0d3aa6
NC
1137static struct bfd_hash_entry *
1138score_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
07d6d2b8
AM
1139 struct bfd_hash_table *table,
1140 const char *string)
1c0d3aa6 1141{
4dfe6ac6 1142 struct score_elf_link_hash_entry *ret = (struct score_elf_link_hash_entry *) entry;
1c0d3aa6
NC
1143
1144 /* Allocate the structure if it has not already been allocated by a subclass. */
1145 if (ret == NULL)
1146 ret = bfd_hash_allocate (table, sizeof (struct score_elf_link_hash_entry));
1147 if (ret == NULL)
4dfe6ac6 1148 return (struct bfd_hash_entry *) ret;
1c0d3aa6
NC
1149
1150 /* Call the allocation method of the superclass. */
1151 ret = ((struct score_elf_link_hash_entry *)
07d6d2b8 1152 _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
1c0d3aa6
NC
1153
1154 if (ret != NULL)
1155 {
1156 ret->possibly_dynamic_relocs = 0;
0a1b45a2
AM
1157 ret->readonly_reloc = false;
1158 ret->no_fn_stub = false;
1159 ret->forced_local = false;
1c0d3aa6
NC
1160 }
1161
4dfe6ac6 1162 return (struct bfd_hash_entry *) ret;
1c0d3aa6
NC
1163}
1164
1165/* Returns the first relocation of type r_type found, beginning with
1166 RELOCATION. RELEND is one-past-the-end of the relocation table. */
1c0d3aa6
NC
1167static const Elf_Internal_Rela *
1168score_elf_next_relocation (bfd *abfd ATTRIBUTE_UNUSED, unsigned int r_type,
07d6d2b8
AM
1169 const Elf_Internal_Rela *relocation,
1170 const Elf_Internal_Rela *relend)
1c0d3aa6
NC
1171{
1172 while (relocation < relend)
1173 {
1174 if (ELF32_R_TYPE (relocation->r_info) == r_type)
07d6d2b8 1175 return relocation;
1c0d3aa6
NC
1176
1177 ++relocation;
1178 }
1179
1180 /* We didn't find it. */
1181 bfd_set_error (bfd_error_bad_value);
1182 return NULL;
1183}
1184
1185/* This function is called via qsort() to sort the dynamic relocation
1186 entries by increasing r_symndx value. */
1c0d3aa6
NC
1187static int
1188score_elf_sort_dynamic_relocs (const void *arg1, const void *arg2)
1189{
1190 Elf_Internal_Rela int_reloc1;
1191 Elf_Internal_Rela int_reloc2;
1192
1193 bfd_elf32_swap_reloc_in (reldyn_sorting_bfd, arg1, &int_reloc1);
1194 bfd_elf32_swap_reloc_in (reldyn_sorting_bfd, arg2, &int_reloc2);
1195
1196 return (ELF32_R_SYM (int_reloc1.r_info) - ELF32_R_SYM (int_reloc2.r_info));
1197}
1198
1199/* Return whether a relocation is against a local symbol. */
0a1b45a2 1200static bool
1c0d3aa6 1201score_elf_local_relocation_p (bfd *input_bfd,
07d6d2b8
AM
1202 const Elf_Internal_Rela *relocation,
1203 asection **local_sections,
0a1b45a2 1204 bool check_forced)
1c0d3aa6
NC
1205{
1206 unsigned long r_symndx;
1207 Elf_Internal_Shdr *symtab_hdr;
1208 struct score_elf_link_hash_entry *h;
1209 size_t extsymoff;
1210
1211 r_symndx = ELF32_R_SYM (relocation->r_info);
1212 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
c3b7224a 1213 extsymoff = (elf_bad_symtab (input_bfd)) ? 0 : symtab_hdr->sh_info;
1c0d3aa6
NC
1214
1215 if (r_symndx < extsymoff)
0a1b45a2 1216 return true;
c3b7224a 1217 if (elf_bad_symtab (input_bfd) && local_sections[r_symndx] != NULL)
0a1b45a2 1218 return true;
1c0d3aa6
NC
1219
1220 if (check_forced)
1221 {
1222 /* Look up the hash table to check whether the symbol was forced local. */
1223 h = (struct score_elf_link_hash_entry *)
07d6d2b8 1224 elf_sym_hashes (input_bfd) [r_symndx - extsymoff];
1c0d3aa6
NC
1225 /* Find the real hash-table entry for this symbol. */
1226 while (h->root.root.type == bfd_link_hash_indirect
07d6d2b8
AM
1227 || h->root.root.type == bfd_link_hash_warning)
1228 h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link;
1c0d3aa6 1229 if (h->root.forced_local)
0a1b45a2 1230 return true;
1c0d3aa6
NC
1231 }
1232
0a1b45a2 1233 return false;
1c0d3aa6
NC
1234}
1235
1236/* Returns the dynamic relocation section for DYNOBJ. */
1c0d3aa6 1237static asection *
0a1b45a2 1238score_elf_rel_dyn_section (bfd *dynobj, bool create_p)
1c0d3aa6
NC
1239{
1240 static const char dname[] = ".rel.dyn";
1241 asection *sreloc;
1242
3d4d4302 1243 sreloc = bfd_get_linker_section (dynobj, dname);
1c0d3aa6
NC
1244 if (sreloc == NULL && create_p)
1245 {
3d4d4302
AM
1246 sreloc = bfd_make_section_anyway_with_flags (dynobj, dname,
1247 (SEC_ALLOC
1248 | SEC_LOAD
1249 | SEC_HAS_CONTENTS
1250 | SEC_IN_MEMORY
1251 | SEC_LINKER_CREATED
1252 | SEC_READONLY));
1c0d3aa6 1253 if (sreloc == NULL
fd361982
AM
1254 || !bfd_set_section_alignment (sreloc,
1255 SCORE_ELF_LOG_FILE_ALIGN (dynobj)))
07d6d2b8 1256 return NULL;
1c0d3aa6 1257 }
c3b7224a 1258 return sreloc;
1c0d3aa6
NC
1259}
1260
1261static void
1262score_elf_allocate_dynamic_relocations (bfd *abfd, unsigned int n)
1263{
1264 asection *s;
1265
0a1b45a2 1266 s = score_elf_rel_dyn_section (abfd, false);
1c0d3aa6
NC
1267 BFD_ASSERT (s != NULL);
1268
1269 if (s->size == 0)
1270 {
1271 /* Make room for a null element. */
1272 s->size += SCORE_ELF_REL_SIZE (abfd);
1273 ++s->reloc_count;
1274 }
1275 s->size += n * SCORE_ELF_REL_SIZE (abfd);
1276}
1277
1278/* Create a rel.dyn relocation for the dynamic linker to resolve. REL
1279 is the original relocation, which is now being transformed into a
1280 dynamic relocation. The ADDENDP is adjusted if necessary; the
1281 caller should store the result in place of the original addend. */
0a1b45a2 1282static bool
1c0d3aa6 1283score_elf_create_dynamic_relocation (bfd *output_bfd,
07d6d2b8
AM
1284 struct bfd_link_info *info,
1285 const Elf_Internal_Rela *rel,
1286 struct score_elf_link_hash_entry *h,
1287 bfd_vma symbol,
1288 bfd_vma *addendp, asection *input_section)
1c0d3aa6
NC
1289{
1290 Elf_Internal_Rela outrel[3];
1291 asection *sreloc;
1292 bfd *dynobj;
1293 int r_type;
1294 long indx;
0a1b45a2 1295 bool defined_p;
1c0d3aa6
NC
1296
1297 r_type = ELF32_R_TYPE (rel->r_info);
1298 dynobj = elf_hash_table (info)->dynobj;
0a1b45a2 1299 sreloc = score_elf_rel_dyn_section (dynobj, false);
1c0d3aa6
NC
1300 BFD_ASSERT (sreloc != NULL);
1301 BFD_ASSERT (sreloc->contents != NULL);
1302 BFD_ASSERT (sreloc->reloc_count * SCORE_ELF_REL_SIZE (output_bfd) < sreloc->size);
1303
1304 outrel[0].r_offset =
1305 _bfd_elf_section_offset (output_bfd, info, input_section, rel[0].r_offset);
1306 outrel[1].r_offset =
1307 _bfd_elf_section_offset (output_bfd, info, input_section, rel[1].r_offset);
1308 outrel[2].r_offset =
1309 _bfd_elf_section_offset (output_bfd, info, input_section, rel[2].r_offset);
1310
1311 if (outrel[0].r_offset == MINUS_ONE)
1312 /* The relocation field has been deleted. */
0a1b45a2 1313 return true;
1c0d3aa6
NC
1314
1315 if (outrel[0].r_offset == MINUS_TWO)
1316 {
1317 /* The relocation field has been converted into a relative value of
07d6d2b8
AM
1318 some sort. Functions like _bfd_elf_write_section_eh_frame expect
1319 the field to be fully relocated, so add in the symbol's value. */
1c0d3aa6 1320 *addendp += symbol;
0a1b45a2 1321 return true;
1c0d3aa6
NC
1322 }
1323
1324 /* We must now calculate the dynamic symbol table index to use
1325 in the relocation. */
1326 if (h != NULL
1327 && (! info->symbolic || !h->root.def_regular)
1328 /* h->root.dynindx may be -1 if this symbol was marked to
07d6d2b8 1329 become local. */
1c0d3aa6
NC
1330 && h->root.dynindx != -1)
1331 {
1332 indx = h->root.dynindx;
07d6d2b8
AM
1333 /* ??? glibc's ld.so just adds the final GOT entry to the
1334 relocation field. It therefore treats relocs against
1335 defined symbols in the same way as relocs against
1336 undefined symbols. */
0a1b45a2 1337 defined_p = false;
1c0d3aa6
NC
1338 }
1339 else
1340 {
9838404f 1341 indx = 0;
0a1b45a2 1342 defined_p = true;
1c0d3aa6
NC
1343 }
1344
1345 /* If the relocation was previously an absolute relocation and
1346 this symbol will not be referred to by the relocation, we must
1347 adjust it by the value we give it in the dynamic symbol table.
1348 Otherwise leave the job up to the dynamic linker. */
1349 if (defined_p && r_type != R_SCORE_REL32)
1350 *addendp += symbol;
1351
1352 /* The relocation is always an REL32 relocation because we don't
1353 know where the shared library will wind up at load-time. */
1354 outrel[0].r_info = ELF32_R_INFO ((unsigned long) indx, R_SCORE_REL32);
1355
1356 /* For strict adherence to the ABI specification, we should
1357 generate a R_SCORE_64 relocation record by itself before the
1358 _REL32/_64 record as well, such that the addend is read in as
1359 a 64-bit value (REL32 is a 32-bit relocation, after all).
1360 However, since none of the existing ELF64 SCORE dynamic
1361 loaders seems to care, we don't waste space with these
1362 artificial relocations. If this turns out to not be true,
1363 score_elf_allocate_dynamic_relocations() should be tweaked so
1364 as to make room for a pair of dynamic relocations per
1365 invocation if ABI_64_P, and here we should generate an
1366 additional relocation record with R_SCORE_64 by itself for a
1367 NULL symbol before this relocation record. */
1368 outrel[1].r_info = ELF32_R_INFO (0, R_SCORE_NONE);
1369 outrel[2].r_info = ELF32_R_INFO (0, R_SCORE_NONE);
1370
1371 /* Adjust the output offset of the relocation to reference the
1372 correct location in the output file. */
1373 outrel[0].r_offset += (input_section->output_section->vma
07d6d2b8 1374 + input_section->output_offset);
1c0d3aa6 1375 outrel[1].r_offset += (input_section->output_section->vma
07d6d2b8 1376 + input_section->output_offset);
1c0d3aa6 1377 outrel[2].r_offset += (input_section->output_section->vma
07d6d2b8 1378 + input_section->output_offset);
1c0d3aa6
NC
1379
1380 /* Put the relocation back out. We have to use the special
1381 relocation outputter in the 64-bit case since the 64-bit
1382 relocation format is non-standard. */
1383 bfd_elf32_swap_reloc_out
1384 (output_bfd, &outrel[0],
1385 (sreloc->contents + sreloc->reloc_count * sizeof (Elf32_External_Rel)));
1386
1387 /* We've now added another relocation. */
1388 ++sreloc->reloc_count;
1389
1390 /* Make sure the output section is writable. The dynamic linker
1391 will be writing to it. */
1392 elf_section_data (input_section->output_section)->this_hdr.sh_flags |= SHF_WRITE;
1393
0a1b45a2 1394 return true;
1c0d3aa6
NC
1395}
1396
0a1b45a2 1397static bool
1c0d3aa6 1398score_elf_create_got_section (bfd *abfd,
07d6d2b8 1399 struct bfd_link_info *info,
0a1b45a2 1400 bool maybe_exclude)
1c0d3aa6
NC
1401{
1402 flagword flags;
1403 asection *s;
1404 struct elf_link_hash_entry *h;
1405 struct bfd_link_hash_entry *bh;
1406 struct score_got_info *g;
986f0783 1407 size_t amt;
1c0d3aa6
NC
1408
1409 /* This function may be called more than once. */
0a1b45a2 1410 s = score_elf_got_section (abfd, true);
1c0d3aa6
NC
1411 if (s)
1412 {
1413 if (! maybe_exclude)
07d6d2b8 1414 s->flags &= ~SEC_EXCLUDE;
0a1b45a2 1415 return true;
1c0d3aa6
NC
1416 }
1417
1418 flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
1419
1420 if (maybe_exclude)
1421 flags |= SEC_EXCLUDE;
1422
1423 /* We have to use an alignment of 2**4 here because this is hardcoded
1424 in the function stub generation and in the linker script. */
3d4d4302 1425 s = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
ce558b89
AM
1426 elf_hash_table (info)->sgot = s;
1427 if (s == NULL
fd361982 1428 || !bfd_set_section_alignment (s, 4))
0a1b45a2 1429 return false;
1c0d3aa6
NC
1430
1431 /* Define the symbol _GLOBAL_OFFSET_TABLE_. We don't do this in the
1432 linker script because we don't want to define the symbol if we
1433 are not creating a global offset table. */
1434 bh = NULL;
1435 if (! (_bfd_generic_link_add_one_symbol
07d6d2b8 1436 (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s,
0a1b45a2
AM
1437 0, NULL, false, get_elf_backend_data (abfd)->collect, &bh)))
1438 return false;
1c0d3aa6
NC
1439
1440 h = (struct elf_link_hash_entry *) bh;
1441 h->non_elf = 0;
1442 h->def_regular = 1;
1443 h->type = STT_OBJECT;
ce558b89 1444 elf_hash_table (info)->hgot = h;
1c0d3aa6 1445
0e1862bb 1446 if (bfd_link_pic (info) && ! bfd_elf_link_record_dynamic_symbol (info, h))
0a1b45a2 1447 return false;
1c0d3aa6
NC
1448
1449 amt = sizeof (struct score_got_info);
1450 g = bfd_alloc (abfd, amt);
1451 if (g == NULL)
0a1b45a2 1452 return false;
1c0d3aa6
NC
1453
1454 g->global_gotsym = NULL;
1455 g->global_gotno = 0;
1456
1457 g->local_gotno = SCORE_RESERVED_GOTNO;
1458 g->assigned_gotno = SCORE_RESERVED_GOTNO;
1459 g->next = NULL;
1460
1461 g->got_entries = htab_try_create (1, score_elf_got_entry_hash,
07d6d2b8 1462 score_elf_got_entry_eq, NULL);
1c0d3aa6 1463 if (g->got_entries == NULL)
0a1b45a2 1464 return false;
1c0d3aa6
NC
1465 score_elf_section_data (s)->u.got_info = g;
1466 score_elf_section_data (s)->elf.this_hdr.sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_SCORE_GPREL;
1467
0a1b45a2 1468 return true;
1c0d3aa6
NC
1469}
1470
1471/* Calculate the %high function. */
1c0d3aa6
NC
1472static bfd_vma
1473score_elf_high (bfd_vma value)
1474{
1475 return ((value + (bfd_vma) 0x8000) >> 16) & 0xffff;
1476}
1477
1478/* Create a local GOT entry for VALUE. Return the index of the entry,
1479 or -1 if it could not be created. */
1c0d3aa6
NC
1480static struct score_got_entry *
1481score_elf_create_local_got_entry (bfd *abfd,
07d6d2b8
AM
1482 bfd *ibfd ATTRIBUTE_UNUSED,
1483 struct score_got_info *gg,
1484 asection *sgot, bfd_vma value,
1485 unsigned long r_symndx ATTRIBUTE_UNUSED,
1486 struct score_elf_link_hash_entry *h ATTRIBUTE_UNUSED,
1487 int r_type ATTRIBUTE_UNUSED)
1c0d3aa6
NC
1488{
1489 struct score_got_entry entry, **loc;
1490 struct score_got_info *g;
1491
1492 entry.abfd = NULL;
1493 entry.symndx = -1;
1494 entry.d.address = value;
1495
1496 g = gg;
1497 loc = (struct score_got_entry **) htab_find_slot (g->got_entries, &entry, INSERT);
1498 if (*loc)
1499 return *loc;
1500
1501 entry.gotidx = SCORE_ELF_GOT_SIZE (abfd) * g->assigned_gotno++;
1502
1503 *loc = bfd_alloc (abfd, sizeof entry);
1504
1505 if (! *loc)
1506 return NULL;
1507
1508 memcpy (*loc, &entry, sizeof entry);
1509
1510 if (g->assigned_gotno >= g->local_gotno)
1511 {
1512 (*loc)->gotidx = -1;
1513 /* We didn't allocate enough space in the GOT. */
4eca0228 1514 _bfd_error_handler
07d6d2b8 1515 (_("not enough GOT space for local GOT entries"));
1c0d3aa6
NC
1516 bfd_set_error (bfd_error_bad_value);
1517 return NULL;
1518 }
1519
c3b7224a 1520 score_bfd_put_32 (abfd, value, (sgot->contents + entry.gotidx));
1c0d3aa6
NC
1521
1522 return *loc;
1523}
1524
1525/* Find a GOT entry whose higher-order 16 bits are the same as those
1526 for value. Return the index into the GOT for this entry. */
1c0d3aa6
NC
1527static bfd_vma
1528score_elf_got16_entry (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
0a1b45a2 1529 bfd_vma value, bool external)
1c0d3aa6
NC
1530{
1531 asection *sgot;
1532 struct score_got_info *g;
1533 struct score_got_entry *entry;
1534
1535 if (!external)
1536 {
1537 /* Although the ABI says that it is "the high-order 16 bits" that we
07d6d2b8
AM
1538 want, it is really the %high value. The complete value is
1539 calculated with a `addiu' of a LO16 relocation, just as with a
1540 HI16/LO16 pair. */
1c0d3aa6
NC
1541 value = score_elf_high (value) << 16;
1542 }
1543
1544 g = score_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
1545
1546 entry = score_elf_create_local_got_entry (abfd, ibfd, g, sgot, value, 0, NULL,
07d6d2b8 1547 R_SCORE_GOT15);
1c0d3aa6
NC
1548 if (entry)
1549 return entry->gotidx;
1550 else
1551 return MINUS_ONE;
1552}
1553
1554static void
c3b7224a 1555s3_bfd_score_elf_hide_symbol (struct bfd_link_info *info,
07d6d2b8 1556 struct elf_link_hash_entry *entry,
0a1b45a2 1557 bool force_local)
1c0d3aa6
NC
1558{
1559 bfd *dynobj;
1560 asection *got;
1561 struct score_got_info *g;
1562 struct score_elf_link_hash_entry *h;
1563
1564 h = (struct score_elf_link_hash_entry *) entry;
1565 if (h->forced_local)
1566 return;
0a1b45a2 1567 h->forced_local = true;
1c0d3aa6
NC
1568
1569 dynobj = elf_hash_table (info)->dynobj;
1570 if (dynobj != NULL && force_local)
1571 {
0a1b45a2 1572 got = score_elf_got_section (dynobj, false);
1c0d3aa6 1573 if (got == NULL)
07d6d2b8 1574 return;
1c0d3aa6
NC
1575 g = score_elf_section_data (got)->u.got_info;
1576
1577 if (g->next)
07d6d2b8
AM
1578 {
1579 struct score_got_entry e;
1580 struct score_got_info *gg = g;
1581
1582 /* Since we're turning what used to be a global symbol into a
1583 local one, bump up the number of local entries of each GOT
1584 that had an entry for it. This will automatically decrease
1585 the number of global entries, since global_gotno is actually
1586 the upper limit of global entries. */
1587 e.abfd = dynobj;
1588 e.symndx = -1;
1589 e.d.h = h;
1590
1591 for (g = g->next; g != gg; g = g->next)
1592 if (htab_find (g->got_entries, &e))
1593 {
1594 BFD_ASSERT (g->global_gotno > 0);
1595 g->local_gotno++;
1596 g->global_gotno--;
1597 }
1598
1599 /* If this was a global symbol forced into the primary GOT, we
1600 no longer need an entry for it. We can't release the entry
1601 at this point, but we must at least stop counting it as one
1602 of the symbols that required a forced got entry. */
1603 if (h->root.got.offset == 2)
1604 {
1605 BFD_ASSERT (gg->assigned_gotno > 0);
1606 gg->assigned_gotno--;
1607 }
1608 }
1c0d3aa6 1609 else if (g->global_gotno == 0 && g->global_gotsym == NULL)
07d6d2b8
AM
1610 /* If we haven't got through GOT allocation yet, just bump up the
1611 number of local entries, as this symbol won't be counted as
1612 global. */
1613 g->local_gotno++;
1c0d3aa6 1614 else if (h->root.got.offset == 1)
07d6d2b8
AM
1615 {
1616 /* If we're past non-multi-GOT allocation and this symbol had
1617 been marked for a global got entry, give it a local entry
1618 instead. */
1619 BFD_ASSERT (g->global_gotno > 0);
1620 g->local_gotno++;
1621 g->global_gotno--;
1622 }
1c0d3aa6
NC
1623 }
1624
1625 _bfd_elf_link_hash_hide_symbol (info, &h->root, force_local);
1626}
1627
1628/* If H is a symbol that needs a global GOT entry, but has a dynamic
1629 symbol table index lower than any we've seen to date, record it for
1630 posterity. */
0a1b45a2 1631static bool
1c0d3aa6 1632score_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
07d6d2b8
AM
1633 bfd *abfd,
1634 struct bfd_link_info *info,
1635 struct score_got_info *g)
1c0d3aa6
NC
1636{
1637 struct score_got_entry entry, **loc;
1638
1639 /* A global symbol in the GOT must also be in the dynamic symbol table. */
1640 if (h->dynindx == -1)
1641 {
1642 switch (ELF_ST_VISIBILITY (h->other))
07d6d2b8
AM
1643 {
1644 case STV_INTERNAL:
1645 case STV_HIDDEN:
0a1b45a2 1646 s3_bfd_score_elf_hide_symbol (info, h, true);
07d6d2b8
AM
1647 break;
1648 }
1c0d3aa6 1649 if (!bfd_elf_link_record_dynamic_symbol (info, h))
0a1b45a2 1650 return false;
1c0d3aa6
NC
1651 }
1652
1653 entry.abfd = abfd;
1654 entry.symndx = -1;
1655 entry.d.h = (struct score_elf_link_hash_entry *)h;
1656
1657 loc = (struct score_got_entry **)htab_find_slot (g->got_entries, &entry, INSERT);
1658
1659 /* If we've already marked this entry as needing GOT space, we don't
1660 need to do it again. */
1661 if (*loc)
0a1b45a2 1662 return true;
1c0d3aa6
NC
1663
1664 *loc = bfd_alloc (abfd, sizeof entry);
1665 if (! *loc)
0a1b45a2 1666 return false;
1c0d3aa6
NC
1667
1668 entry.gotidx = -1;
1669
1670 memcpy (*loc, &entry, sizeof (entry));
1671
1672 if (h->got.offset != MINUS_ONE)
0a1b45a2 1673 return true;
1c0d3aa6
NC
1674
1675 /* By setting this to a value other than -1, we are indicating that
1676 there needs to be a GOT entry for H. Avoid using zero, as the
1677 generic ELF copy_indirect_symbol tests for <= 0. */
1678 h->got.offset = 1;
1679
0a1b45a2 1680 return true;
1c0d3aa6
NC
1681}
1682
1683/* Reserve space in G for a GOT entry containing the value of symbol
1684 SYMNDX in input bfd ABDF, plus ADDEND. */
0a1b45a2 1685static bool
1c0d3aa6 1686score_elf_record_local_got_symbol (bfd *abfd,
07d6d2b8
AM
1687 long symndx,
1688 bfd_vma addend,
1689 struct score_got_info *g)
1c0d3aa6
NC
1690{
1691 struct score_got_entry entry, **loc;
1692
1693 entry.abfd = abfd;
1694 entry.symndx = symndx;
1695 entry.d.addend = addend;
1696 loc = (struct score_got_entry **)htab_find_slot (g->got_entries, &entry, INSERT);
1697
1698 if (*loc)
0a1b45a2 1699 return true;
1c0d3aa6
NC
1700
1701 entry.gotidx = g->local_gotno++;
1702
1703 *loc = bfd_alloc (abfd, sizeof(entry));
1704 if (! *loc)
0a1b45a2 1705 return false;
1c0d3aa6
NC
1706
1707 memcpy (*loc, &entry, sizeof (entry));
1708
0a1b45a2 1709 return true;
1c0d3aa6
NC
1710}
1711
1712/* Returns the GOT offset at which the indicated address can be found.
1713 If there is not yet a GOT entry for this value, create one.
1714 Returns -1 if no satisfactory GOT offset can be found. */
1c0d3aa6
NC
1715static bfd_vma
1716score_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
07d6d2b8
AM
1717 bfd_vma value, unsigned long r_symndx,
1718 struct score_elf_link_hash_entry *h, int r_type)
1c0d3aa6
NC
1719{
1720 asection *sgot;
1721 struct score_got_info *g;
1722 struct score_got_entry *entry;
1723
1724 g = score_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
1725
1726 entry = score_elf_create_local_got_entry (abfd, ibfd, g, sgot, value,
07d6d2b8 1727 r_symndx, h, r_type);
1c0d3aa6
NC
1728 if (!entry)
1729 return MINUS_ONE;
1730
1731 else
1732 return entry->gotidx;
1733}
1734
1735/* Returns the GOT index for the global symbol indicated by H. */
1736
1737static bfd_vma
1738score_elf_global_got_index (bfd *abfd, struct elf_link_hash_entry *h)
1739{
91d6fa6a 1740 bfd_vma got_index;
1c0d3aa6
NC
1741 asection *sgot;
1742 struct score_got_info *g;
1743 long global_got_dynindx = 0;
1744
1745 g = score_elf_got_info (abfd, &sgot);
1746 if (g->global_gotsym != NULL)
1747 global_got_dynindx = g->global_gotsym->dynindx;
1748
1749 /* Once we determine the global GOT entry with the lowest dynamic
1750 symbol table index, we must put all dynamic symbols with greater
1751 indices into the GOT. That makes it easy to calculate the GOT
1752 offset. */
1753 BFD_ASSERT (h->dynindx >= global_got_dynindx);
91d6fa6a
NC
1754 got_index = ((h->dynindx - global_got_dynindx + g->local_gotno) * SCORE_ELF_GOT_SIZE (abfd));
1755 BFD_ASSERT (got_index < sgot->size);
1c0d3aa6 1756
91d6fa6a 1757 return got_index;
1c0d3aa6
NC
1758}
1759
1760/* Returns the offset for the entry at the INDEXth position in the GOT. */
91d6fa6a 1761
1c0d3aa6 1762static bfd_vma
91d6fa6a
NC
1763score_elf_got_offset_from_index (bfd *dynobj,
1764 bfd *output_bfd,
07d6d2b8 1765 bfd *input_bfd ATTRIBUTE_UNUSED,
91d6fa6a 1766 bfd_vma got_index)
1c0d3aa6
NC
1767{
1768 asection *sgot;
1769 bfd_vma gp;
1c0d3aa6 1770
c7e2358a 1771 score_elf_got_info (dynobj, &sgot);
1c0d3aa6
NC
1772 gp = _bfd_get_gp_value (output_bfd);
1773
91d6fa6a 1774 return sgot->output_section->vma + sgot->output_offset + got_index - gp;
1c0d3aa6
NC
1775}
1776
1777/* Follow indirect and warning hash entries so that each got entry
1778 points to the final symbol definition. P must point to a pointer
1779 to the hash table we're traversing. Since this traversal may
1780 modify the hash table, we set this pointer to NULL to indicate
1781 we've made a potentially-destructive change to the hash table, so
1782 the traversal must be restarted. */
1783static int
1784score_elf_resolve_final_got_entry (void **entryp, void *p)
1785{
1786 struct score_got_entry *entry = (struct score_got_entry *)*entryp;
1787 htab_t got_entries = *(htab_t *)p;
1788
1789 if (entry->abfd != NULL && entry->symndx == -1)
1790 {
1791 struct score_elf_link_hash_entry *h = entry->d.h;
1792
1793 while (h->root.root.type == bfd_link_hash_indirect
07d6d2b8
AM
1794 || h->root.root.type == bfd_link_hash_warning)
1795 h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link;
1c0d3aa6
NC
1796
1797 if (entry->d.h == h)
07d6d2b8 1798 return 1;
1c0d3aa6
NC
1799
1800 entry->d.h = h;
1801
1802 /* If we can't find this entry with the new bfd hash, re-insert
07d6d2b8 1803 it, and get the traversal restarted. */
1c0d3aa6 1804 if (! htab_find (got_entries, entry))
07d6d2b8
AM
1805 {
1806 htab_clear_slot (got_entries, entryp);
1807 entryp = htab_find_slot (got_entries, entry, INSERT);
1808 if (! *entryp)
1809 *entryp = entry;
1810 /* Abort the traversal, since the whole table may have
1811 moved, and leave it up to the parent to restart the
1812 process. */
1813 *(htab_t *)p = NULL;
1814 return 0;
1815 }
1c0d3aa6 1816 /* We might want to decrement the global_gotno count, but it's
07d6d2b8 1817 either too early or too late for that at this point. */
1c0d3aa6
NC
1818 }
1819
1820 return 1;
1821}
1822
1823/* Turn indirect got entries in a got_entries table into their final locations. */
1824static void
1825score_elf_resolve_final_got_entries (struct score_got_info *g)
1826{
1827 htab_t got_entries;
1828
1829 do
1830 {
1831 got_entries = g->got_entries;
1832
1833 htab_traverse (got_entries,
07d6d2b8
AM
1834 score_elf_resolve_final_got_entry,
1835 &got_entries);
1c0d3aa6
NC
1836 }
1837 while (got_entries == NULL);
1838}
1839
1840/* Add INCREMENT to the reloc (of type HOWTO) at ADDRESS. for -r */
1c0d3aa6
NC
1841static void
1842score_elf_add_to_rel (bfd *abfd,
07d6d2b8
AM
1843 bfd_byte *address,
1844 reloc_howto_type *howto,
1845 bfd_signed_vma increment)
1c0d3aa6
NC
1846{
1847 bfd_signed_vma addend;
1848 bfd_vma contents;
1849 unsigned long offset;
1850 unsigned long r_type = howto->type;
1851 unsigned long hi16_addend, hi16_offset, hi16_value, uvalue;
1852
c3b7224a 1853 contents = score_bfd_get_32 (abfd, address);
1c0d3aa6
NC
1854 /* Get the (signed) value from the instruction. */
1855 addend = contents & howto->src_mask;
1856 if (addend & ((howto->src_mask + 1) >> 1))
1857 {
1858 bfd_signed_vma mask;
1859
1860 mask = -1;
1861 mask &= ~howto->src_mask;
1862 addend |= mask;
1863 }
1864 /* Add in the increment, (which is a byte value). */
1865 switch (r_type)
1866 {
1867 case R_SCORE_PC19:
1868 offset =
07d6d2b8 1869 (((contents & howto->src_mask) & 0x3ff0000) >> 6) | ((contents & howto->src_mask) & 0x3ff);
1c0d3aa6
NC
1870 offset += increment;
1871 contents =
07d6d2b8
AM
1872 (contents & ~howto->
1873 src_mask) | (((offset << 6) & howto->src_mask) & 0x3ff0000) | (offset & 0x3ff);
c3b7224a 1874 score_bfd_put_32 (abfd, contents, address);
1c0d3aa6
NC
1875 break;
1876 case R_SCORE_HI16:
1877 break;
1878 case R_SCORE_LO16:
c3b7224a 1879 hi16_addend = score_bfd_get_32 (abfd, address - 4);
1c0d3aa6
NC
1880 hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1;
1881 offset = ((((contents >> 16) & 0x3) << 15) | (contents & 0x7fff)) >> 1;
1882 offset = (hi16_offset << 16) | (offset & 0xffff);
1883 uvalue = increment + offset;
1884 hi16_offset = (uvalue >> 16) << 1;
1885 hi16_value = (hi16_addend & (~(howto->dst_mask)))
07d6d2b8 1886 | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
c3b7224a 1887 score_bfd_put_32 (abfd, hi16_value, address - 4);
1c0d3aa6
NC
1888 offset = (uvalue & 0xffff) << 1;
1889 contents = (contents & (~(howto->dst_mask))) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
c3b7224a 1890 score_bfd_put_32 (abfd, contents, address);
1c0d3aa6
NC
1891 break;
1892 case R_SCORE_24:
1893 offset =
07d6d2b8 1894 (((contents & howto->src_mask) >> 1) & 0x1ff8000) | ((contents & howto->src_mask) & 0x7fff);
1c0d3aa6
NC
1895 offset += increment;
1896 contents =
07d6d2b8
AM
1897 (contents & ~howto->
1898 src_mask) | (((offset << 1) & howto->src_mask) & 0x3ff0000) | (offset & 0x7fff);
c3b7224a 1899 score_bfd_put_32 (abfd, contents, address);
1c0d3aa6 1900 break;
c3b7224a 1901
1c0d3aa6
NC
1902 case R_SCORE16_11:
1903
c3b7224a 1904 contents = score_bfd_get_16 (abfd, address);
1c0d3aa6
NC
1905 offset = contents & howto->src_mask;
1906 offset += increment;
1907 contents = (contents & ~howto->src_mask) | (offset & howto->src_mask);
c3b7224a 1908 score_bfd_put_16 (abfd, contents, address);
1c0d3aa6
NC
1909
1910 break;
1911 case R_SCORE16_PC8:
1912
c3b7224a
NC
1913 contents = score_bfd_get_16 (abfd, address);
1914 offset = (contents & howto->src_mask) + ((increment >> 1) & 0x1ff);
1915 contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask);
1916 score_bfd_put_16 (abfd, contents, address);
1917
1918 break;
1919
1920 case R_SCORE_BCMP:
1921 contents = score_bfd_get_32 (abfd, address);
1922 offset = (contents & howto->src_mask);
1923 offset <<= howto->rightshift;
1924 offset += increment;
1925 offset >>= howto->rightshift;
1926 contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask);
1927 score_bfd_put_32 (abfd, contents, address);
1928 break;
1929
1930 case R_SCORE_IMM30:
1931 contents = score_bfd_get_48 (abfd, address);
1932 offset = (contents & howto->src_mask);
1933 offset <<= howto->rightshift;
1934 offset += increment;
1935 offset >>= howto->rightshift;
1c0d3aa6 1936 contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask);
c3b7224a
NC
1937 score_bfd_put_48 (abfd, contents, address);
1938 break;
1c0d3aa6 1939
c3b7224a
NC
1940 case R_SCORE_IMM32:
1941 contents = score_bfd_get_48 (abfd, address);
1942 offset = (contents & howto->src_mask);
1943 offset += increment;
1944 contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask);
1945 score_bfd_put_48 (abfd, contents, address);
1c0d3aa6 1946 break;
c3b7224a 1947
1c0d3aa6
NC
1948 default:
1949 addend += increment;
1950 contents = (contents & ~howto->dst_mask) | (addend & howto->dst_mask);
c3b7224a 1951 score_bfd_put_32 (abfd, contents, address);
1c0d3aa6
NC
1952 break;
1953 }
1954}
1955
1956/* Perform a relocation as part of a final link. */
1c0d3aa6
NC
1957static bfd_reloc_status_type
1958score_elf_final_link_relocate (reloc_howto_type *howto,
07d6d2b8
AM
1959 bfd *input_bfd,
1960 bfd *output_bfd,
1961 asection *input_section,
1962 bfd_byte *contents,
1963 Elf_Internal_Rela *rel,
1964 Elf_Internal_Rela *relocs,
1965 bfd_vma symbol,
1966 struct bfd_link_info *info,
1967 const char *sym_name ATTRIBUTE_UNUSED,
1968 int sym_flags ATTRIBUTE_UNUSED,
1969 struct score_elf_link_hash_entry *h,
1970 asection **local_sections,
0a1b45a2 1971 bool gp_disp_p)
1c0d3aa6
NC
1972{
1973 unsigned long r_type;
1974 unsigned long r_symndx;
1975 bfd_byte *hit_data = contents + rel->r_offset;
1976 bfd_vma addend;
1977 /* The final GP value to be used for the relocatable, executable, or
1978 shared object file being produced. */
1979 bfd_vma gp = MINUS_ONE;
1980 /* The place (section offset or address) of the storage unit being relocated. */
1981 bfd_vma rel_addr;
1c0d3aa6
NC
1982 /* The offset into the global offset table at which the address of the relocation entry
1983 symbol, adjusted by the addend, resides during execution. */
1984 bfd_vma g = MINUS_ONE;
1985 /* TRUE if the symbol referred to by this relocation is a local symbol. */
0a1b45a2 1986 bool local_p;
1c0d3aa6
NC
1987 /* The eventual value we will relocate. */
1988 bfd_vma value = symbol;
1989 unsigned long hi16_addend, hi16_offset, hi16_value, uvalue, offset, abs_value = 0;
1990
c3b7224a 1991
1c0d3aa6
NC
1992 if (elf_gp (output_bfd) == 0)
1993 {
1994 struct bfd_link_hash_entry *bh;
1995 asection *o;
1996
1997 bh = bfd_link_hash_lookup (info->hash, "_gp", 0, 0, 1);
c3b7224a 1998 if (bh != NULL && bh->type == bfd_link_hash_defined)
07d6d2b8
AM
1999 elf_gp (output_bfd) = (bh->u.def.value
2000 + bh->u.def.section->output_section->vma
2001 + bh->u.def.section->output_offset);
0e1862bb 2002 else if (bfd_link_relocatable (info))
07d6d2b8
AM
2003 {
2004 bfd_vma lo = -1;
2005
2006 /* Find the GP-relative section with the lowest offset. */
2007 for (o = output_bfd->sections; o != NULL; o = o->next)
2008 if (o->vma < lo)
2009 lo = o->vma;
2010 /* And calculate GP relative to that. */
2011 elf_gp (output_bfd) = lo + ELF_SCORE_GP_OFFSET (input_bfd);
2012 }
1c0d3aa6 2013 else
07d6d2b8
AM
2014 {
2015 /* If the relocate_section function needs to do a reloc
2016 involving the GP value, it should make a reloc_dangerous
2017 callback to warn that GP is not defined. */
2018 }
1c0d3aa6
NC
2019 }
2020
2021 /* Parse the relocation. */
2022 r_symndx = ELF32_R_SYM (rel->r_info);
2023 r_type = ELF32_R_TYPE (rel->r_info);
2024 rel_addr = (input_section->output_section->vma + input_section->output_offset + rel->r_offset);
0a1b45a2 2025 local_p = score_elf_local_relocation_p (input_bfd, rel, local_sections, true);
1c0d3aa6 2026
1c0d3aa6
NC
2027 if (r_type == R_SCORE_GOT15)
2028 {
2029 const Elf_Internal_Rela *relend;
2030 const Elf_Internal_Rela *lo16_rel;
1c0d3aa6
NC
2031 bfd_vma lo_value = 0;
2032
056bafd4 2033 relend = relocs + input_section->reloc_count;
1c0d3aa6 2034 lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend);
0150d082 2035 if ((local_p) && (lo16_rel != NULL))
07d6d2b8
AM
2036 {
2037 bfd_vma tmp = 0;
2038 tmp = score_bfd_get_32 (input_bfd, contents + lo16_rel->r_offset);
2039 lo_value = (((tmp >> 16) & 0x3) << 14) | ((tmp & 0x7fff) >> 1);
2040 }
0150d082 2041 addend = lo_value;
1c0d3aa6 2042 }
c3b7224a
NC
2043 /* For score3 R_SCORE_ABS32. */
2044 else if (r_type == R_SCORE_ABS32 || r_type == R_SCORE_REL32)
1c0d3aa6
NC
2045 {
2046 addend = (bfd_get_32 (input_bfd, hit_data) >> howto->bitpos) & howto->src_mask;
2047 }
c3b7224a
NC
2048 else
2049 {
2050 addend = (score_bfd_get_32 (input_bfd, hit_data) >> howto->bitpos) & howto->src_mask;
2051 }
1c0d3aa6 2052
1c0d3aa6
NC
2053 /* If we haven't already determined the GOT offset, or the GP value,
2054 and we're going to need it, get it now. */
2055 switch (r_type)
2056 {
2057 case R_SCORE_CALL15:
2058 case R_SCORE_GOT15:
2059 if (!local_p)
07d6d2b8
AM
2060 {
2061 g = score_elf_global_got_index (elf_hash_table (info)->dynobj,
2062 (struct elf_link_hash_entry *) h);
2063 if ((! elf_hash_table (info)->dynamic_sections_created
2064 || (bfd_link_pic (info)
2065 && (info->symbolic || h->root.dynindx == -1)
2066 && h->root.def_regular)))
2067 {
2068 /* This is a static link or a -Bsymbolic link. The
2069 symbol is defined locally, or was forced to be local.
2070 We must initialize this entry in the GOT. */
2071 bfd *tmpbfd = elf_hash_table (info)->dynobj;
0a1b45a2 2072 asection *sgot = score_elf_got_section (tmpbfd, false);
07d6d2b8
AM
2073 score_bfd_put_32 (tmpbfd, value, sgot->contents + g);
2074 }
2075 }
1c0d3aa6 2076 else if (r_type == R_SCORE_GOT15 || r_type == R_SCORE_CALL15)
07d6d2b8
AM
2077 {
2078 /* There's no need to create a local GOT entry here; the
2079 calculation for a local GOT15 entry does not involve G. */
2080 ;
2081 }
1c0d3aa6 2082 else
07d6d2b8
AM
2083 {
2084 g = score_elf_local_got_index (output_bfd, input_bfd, info,
2085 symbol + addend, r_symndx, h, r_type);
2086 if (g == MINUS_ONE)
2087 return bfd_reloc_outofrange;
2088 }
1c0d3aa6
NC
2089
2090 /* Convert GOT indices to actual offsets. */
2091 g = score_elf_got_offset_from_index (elf_hash_table (info)->dynobj,
07d6d2b8 2092 output_bfd, input_bfd, g);
1c0d3aa6
NC
2093 break;
2094
2095 case R_SCORE_HI16:
2096 case R_SCORE_LO16:
2097 case R_SCORE_GPREL32:
1c0d3aa6
NC
2098 gp = _bfd_get_gp_value (output_bfd);
2099 break;
2100
2101 case R_SCORE_GP15:
2102 gp = _bfd_get_gp_value (output_bfd);
2103
2104 default:
2105 break;
2106 }
2107
2108 switch (r_type)
2109 {
2110 case R_SCORE_NONE:
2111 return bfd_reloc_ok;
2112
2113 case R_SCORE_ABS32:
2114 case R_SCORE_REL32:
0e1862bb 2115 if ((bfd_link_pic (info)
07d6d2b8
AM
2116 || (elf_hash_table (info)->dynamic_sections_created
2117 && h != NULL
2118 && h->root.def_dynamic
2119 && !h->root.def_regular))
2120 && r_symndx != STN_UNDEF
2121 && (input_section->flags & SEC_ALLOC) != 0)
2122 {
2123 /* If we're creating a shared library, or this relocation is against a symbol
2124 in a shared library, then we can't know where the symbol will end up.
2125 So, we create a relocation record in the output, and leave the job up
2126 to the dynamic linker. */
2127 value = addend;
2128 if (!score_elf_create_dynamic_relocation (output_bfd, info, rel, h,
2129 symbol, &value,
2130 input_section))
2131 return bfd_reloc_undefined;
2132 }
cf35638d 2133 else if (r_symndx == STN_UNDEF)
07d6d2b8
AM
2134 /* r_symndx will be STN_UNDEF (zero) only for relocs against symbols
2135 from removed linkonce sections, or sections discarded by
2136 a linker script. */
2137 value = 0;
1c0d3aa6 2138 else
07d6d2b8
AM
2139 {
2140 if (r_type != R_SCORE_REL32)
2141 value = symbol + addend;
2142 else
2143 value = addend;
2144 }
1c0d3aa6
NC
2145 value &= howto->dst_mask;
2146 bfd_put_32 (input_bfd, value, hit_data);
2147 return bfd_reloc_ok;
2148
2149 case R_SCORE_ABS16:
2150 value += addend;
2151 if ((long)value > 0x7fff || (long)value < -0x8000)
07d6d2b8 2152 return bfd_reloc_overflow;
c3b7224a 2153 score_bfd_put_16 (input_bfd, value, hit_data);
1c0d3aa6
NC
2154 return bfd_reloc_ok;
2155
2156 case R_SCORE_24:
c3b7224a 2157 addend = score_bfd_get_32 (input_bfd, hit_data);
1c0d3aa6
NC
2158 offset = (((addend & howto->src_mask) >> 1) & 0x1ff8000) | ((addend & howto->src_mask) & 0x7fff);
2159 if ((offset & 0x1000000) != 0)
07d6d2b8 2160 offset |= 0xfe000000;
1c0d3aa6 2161 value += offset;
b6518b38 2162 abs_value = value - rel_addr;
c3b7224a 2163 if ((abs_value & 0xfe000000) != 0)
07d6d2b8 2164 return bfd_reloc_overflow;
1c0d3aa6 2165 addend = (addend & ~howto->src_mask)
07d6d2b8 2166 | (((value << 1) & howto->src_mask) & 0x3ff0000) | (value & 0x7fff);
c3b7224a 2167 score_bfd_put_32 (input_bfd, addend, hit_data);
1c0d3aa6
NC
2168 return bfd_reloc_ok;
2169
c3b7224a
NC
2170 /* signed imm32. */
2171 case R_SCORE_IMM30:
2172 {
07d6d2b8
AM
2173 int not_word_align_p = 0;
2174 bfd_vma imm_offset = 0;
2175 addend = score_bfd_get_48 (input_bfd, hit_data);
2176 imm_offset = ((addend >> 7) & 0xff)
2177 | (((addend >> 16) & 0x7fff) << 8)
2178 | (((addend >> 32) & 0x7f) << 23);
2179 imm_offset <<= howto->rightshift;
2180 value += imm_offset;
2181 value &= 0xffffffff;
2182
2183 /* Check lw48/sw48 rd, value/label word align. */
2184 if ((value & 0x3) != 0)
2185 not_word_align_p = 1;
2186
2187 value >>= howto->rightshift;
2188 addend = (addend & ~howto->src_mask)
2189 | (((value & 0xff) >> 0) << 7)
2190 | (((value & 0x7fff00) >> 8) << 16)
2191 | (((value & 0x3f800000) >> 23) << 32);
2192 score_bfd_put_48 (input_bfd, addend, hit_data);
2193 if (not_word_align_p)
2194 return bfd_reloc_other;
2195 else
2196 return bfd_reloc_ok;
c3b7224a
NC
2197 }
2198
2199 case R_SCORE_IMM32:
2200 {
07d6d2b8
AM
2201 bfd_vma imm_offset = 0;
2202 addend = score_bfd_get_48 (input_bfd, hit_data);
2203 imm_offset = ((addend >> 5) & 0x3ff)
2204 | (((addend >> 16) & 0x7fff) << 10)
2205 | (((addend >> 32) & 0x7f) << 25);
2206 value += imm_offset;
2207 value &= 0xffffffff;
2208 addend = (addend & ~howto->src_mask)
2209 | ((value & 0x3ff) << 5)
2210 | (((value >> 10) & 0x7fff) << 16)
2211 | (((value >> 25) & 0x7f) << 32);
2212 score_bfd_put_48 (input_bfd, addend, hit_data);
2213 return bfd_reloc_ok;
c3b7224a
NC
2214 }
2215
1c0d3aa6 2216 case R_SCORE_PC19:
c3b7224a 2217 addend = score_bfd_get_32 (input_bfd, hit_data);
1c0d3aa6
NC
2218 offset = (((addend & howto->src_mask) & 0x3ff0000) >> 6) | ((addend & howto->src_mask) & 0x3ff);
2219 if ((offset & 0x80000) != 0)
07d6d2b8 2220 offset |= 0xfff00000;
1c0d3aa6
NC
2221 abs_value = value = value - rel_addr + offset;
2222 /* exceed 20 bit : overflow. */
2223 if ((abs_value & 0x80000000) == 0x80000000)
07d6d2b8 2224 abs_value = 0xffffffff - value + 1;
1c0d3aa6 2225 if ((abs_value & 0xfff80000) != 0)
07d6d2b8 2226 return bfd_reloc_overflow;
1c0d3aa6 2227 addend = (addend & ~howto->src_mask)
07d6d2b8 2228 | (((value << 6) & howto->src_mask) & 0x3ff0000) | (value & 0x3ff);
c3b7224a 2229 score_bfd_put_32 (input_bfd, addend, hit_data);
1c0d3aa6
NC
2230 return bfd_reloc_ok;
2231
2232 case R_SCORE16_11:
c3b7224a 2233 addend = score_bfd_get_16 (input_bfd, hit_data);
1c0d3aa6 2234 offset = addend & howto->src_mask;
07d6d2b8
AM
2235 if ((offset & 0x800) != 0) /* Offset is negative. */
2236 offset |= 0xfffff000;
1c0d3aa6 2237 value += offset;
b6518b38 2238 abs_value = value - rel_addr;
c3b7224a 2239 if ((abs_value & 0xfffff000) != 0)
07d6d2b8 2240 return bfd_reloc_overflow;
1c0d3aa6 2241 addend = (addend & ~howto->src_mask) | (value & howto->src_mask);
c3b7224a 2242 score_bfd_put_16 (input_bfd, addend, hit_data);
1c0d3aa6
NC
2243 return bfd_reloc_ok;
2244
2245 case R_SCORE16_PC8:
c3b7224a 2246 addend = score_bfd_get_16 (input_bfd, hit_data);
1c0d3aa6 2247 offset = (addend & howto->src_mask) << 1;
07d6d2b8
AM
2248 if ((offset & 0x200) != 0) /* Offset is negative. */
2249 offset |= 0xfffffe00;
1c0d3aa6
NC
2250 abs_value = value = value - rel_addr + offset;
2251 /* Sign bit + exceed 9 bit. */
c3b7224a 2252 if (((value & 0xfffffe00) != 0) && ((value & 0xfffffe00) != 0xfffffe00))
07d6d2b8 2253 return bfd_reloc_overflow;
1c0d3aa6
NC
2254 value >>= 1;
2255 addend = (addend & ~howto->src_mask) | (value & howto->src_mask);
c3b7224a
NC
2256 score_bfd_put_16 (input_bfd, addend, hit_data);
2257 return bfd_reloc_ok;
2258
2259 case R_SCORE_BCMP:
2260 addend = score_bfd_get_32 (input_bfd, hit_data);
2261 offset = (addend & howto->src_mask) << howto->rightshift;
07d6d2b8
AM
2262 if ((offset & 0x200) != 0) /* Offset is negative. */
2263 offset |= 0xfffffe00;
c3b7224a
NC
2264 value = value - rel_addr + offset;
2265 /* Sign bit + exceed 9 bit. */
2266 if (((value & 0xfffffe00) != 0) && ((value & 0xfffffe00) != 0xfffffe00))
07d6d2b8 2267 return bfd_reloc_overflow;
c3b7224a
NC
2268 value >>= howto->rightshift;
2269 addend = (addend & ~howto->src_mask)
07d6d2b8
AM
2270 | (value & 0x1)
2271 | (((value >> 1) & 0x7) << 7)
2272 | (((value >> 4) & 0x1f) << 21);
c3b7224a 2273 score_bfd_put_32 (input_bfd, addend, hit_data);
1c0d3aa6
NC
2274 return bfd_reloc_ok;
2275
2276 case R_SCORE_HI16:
2277 return bfd_reloc_ok;
2278
2279 case R_SCORE_LO16:
c3b7224a 2280 hi16_addend = score_bfd_get_32 (input_bfd, hit_data - 4);
1c0d3aa6 2281 hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1;
c3b7224a 2282 addend = score_bfd_get_32 (input_bfd, hit_data);
1c0d3aa6
NC
2283 offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1;
2284 offset = (hi16_offset << 16) | (offset & 0xffff);
2285
2286 if (!gp_disp_p)
07d6d2b8 2287 uvalue = value + offset;
1c0d3aa6 2288 else
07d6d2b8 2289 uvalue = offset + gp - rel_addr + 4;
1c0d3aa6
NC
2290
2291 hi16_offset = (uvalue >> 16) << 1;
2292 hi16_value = (hi16_addend & (~(howto->dst_mask)))
07d6d2b8 2293 | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
c3b7224a 2294 score_bfd_put_32 (input_bfd, hi16_value, hit_data - 4);
1c0d3aa6
NC
2295 offset = (uvalue & 0xffff) << 1;
2296 value = (addend & (~(howto->dst_mask))) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
c3b7224a 2297 score_bfd_put_32 (input_bfd, value, hit_data);
1c0d3aa6
NC
2298 return bfd_reloc_ok;
2299
2300 case R_SCORE_GP15:
c3b7224a 2301 addend = score_bfd_get_32 (input_bfd, hit_data);
1c0d3aa6
NC
2302 offset = addend & 0x7fff;
2303 if ((offset & 0x4000) == 0x4000)
07d6d2b8 2304 offset |= 0xffffc000;
1c0d3aa6
NC
2305 value = value + offset - gp;
2306 if (((value & 0xffffc000) != 0) && ((value & 0xffffc000) != 0xffffc000))
07d6d2b8 2307 return bfd_reloc_overflow;
1c0d3aa6 2308 value = (addend & ~howto->src_mask) | (value & howto->src_mask);
c3b7224a 2309 score_bfd_put_32 (input_bfd, value, hit_data);
1c0d3aa6
NC
2310 return bfd_reloc_ok;
2311
2312 case R_SCORE_GOT15:
2313 case R_SCORE_CALL15:
2314 if (local_p)
07d6d2b8 2315 {
0a1b45a2 2316 bool forced;
07d6d2b8
AM
2317
2318 /* The special case is when the symbol is forced to be local. We need the
2319 full address in the GOT since no R_SCORE_GOT_LO16 relocation follows. */
2320 forced = ! score_elf_local_relocation_p (input_bfd, rel,
0a1b45a2 2321 local_sections, false);
07d6d2b8
AM
2322 value = score_elf_got16_entry (output_bfd, input_bfd, info,
2323 symbol + addend, forced);
2324 if (value == MINUS_ONE)
2325 return bfd_reloc_outofrange;
2326 value = score_elf_got_offset_from_index (elf_hash_table (info)->dynobj,
2327 output_bfd, input_bfd, value);
2328 }
1c0d3aa6 2329 else
07d6d2b8
AM
2330 {
2331 value = g;
2332 }
1c0d3aa6
NC
2333
2334 if ((long) value > 0x3fff || (long) value < -0x4000)
07d6d2b8 2335 return bfd_reloc_overflow;
0150d082 2336
c3b7224a 2337 addend = score_bfd_get_32 (input_bfd, hit_data);
0150d082 2338 value = (addend & ~howto->dst_mask) | (value & howto->dst_mask);
c3b7224a 2339 score_bfd_put_32 (input_bfd, value, hit_data);
1c0d3aa6
NC
2340 return bfd_reloc_ok;
2341
2342 case R_SCORE_GPREL32:
2343 value = (addend + symbol - gp);
2344 value &= howto->dst_mask;
c3b7224a 2345 score_bfd_put_32 (input_bfd, value, hit_data);
1c0d3aa6
NC
2346 return bfd_reloc_ok;
2347
2348 case R_SCORE_GOT_LO16:
c3b7224a 2349 addend = score_bfd_get_32 (input_bfd, hit_data);
0150d082 2350 value = (((addend >> 16) & 0x3) << 14) | ((addend & 0x7fff) >> 1);
1c0d3aa6 2351 value += symbol;
c3b7224a 2352 value = (addend & (~(howto->dst_mask))) | ((value & 0x3fff) << 1)
07d6d2b8 2353 | (((value >> 14) & 0x3) << 16);
1c0d3aa6 2354
c3b7224a 2355 score_bfd_put_32 (input_bfd, value, hit_data);
1c0d3aa6
NC
2356 return bfd_reloc_ok;
2357
2358 case R_SCORE_DUMMY_HI16:
2359 return bfd_reloc_ok;
2360
2361 case R_SCORE_GNU_VTINHERIT:
2362 case R_SCORE_GNU_VTENTRY:
2363 /* We don't do anything with these at present. */
2364 return bfd_reloc_continue;
2365
2366 default:
2367 return bfd_reloc_notsupported;
2368 }
2369}
2370
2371/* Score backend functions. */
0a1b45a2 2372static bool
599c86c4 2373s3_bfd_score_info_to_howto (bfd *abfd,
07d6d2b8
AM
2374 arelent *bfd_reloc,
2375 Elf_Internal_Rela *elf_reloc)
1c0d3aa6
NC
2376{
2377 unsigned int r_type;
2378
2379 r_type = ELF32_R_TYPE (elf_reloc->r_info);
c3b7224a 2380 if (r_type >= ARRAY_SIZE (elf32_score_howto_table))
599c86c4
AM
2381 {
2382 /* xgettext:c-format */
2383 _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
2384 abfd, r_type);
2385 bfd_set_error (bfd_error_bad_value);
0a1b45a2 2386 return false;
599c86c4 2387 }
f3185997
NC
2388
2389 bfd_reloc->howto = &elf32_score_howto_table[r_type];
0a1b45a2 2390 return true;
1c0d3aa6
NC
2391}
2392
2393/* Relocate an score ELF section. */
0f684201 2394static int
c3b7224a 2395s3_bfd_score_elf_relocate_section (bfd *output_bfd,
07d6d2b8
AM
2396 struct bfd_link_info *info,
2397 bfd *input_bfd,
2398 asection *input_section,
2399 bfd_byte *contents,
2400 Elf_Internal_Rela *relocs,
2401 Elf_Internal_Sym *local_syms,
2402 asection **local_sections)
1c0d3aa6
NC
2403{
2404 Elf_Internal_Shdr *symtab_hdr;
1c0d3aa6
NC
2405 Elf_Internal_Rela *rel;
2406 Elf_Internal_Rela *relend;
2407 const char *name;
2408 unsigned long offset;
2409 unsigned long hi16_addend, hi16_offset, hi16_value, uvalue;
2410 size_t extsymoff;
0a1b45a2 2411 bool gp_disp_p = false;
1c0d3aa6 2412
1c0d3aa6
NC
2413 /* Sort dynsym. */
2414 if (elf_hash_table (info)->dynamic_sections_created)
2415 {
2416 bfd_size_type dynsecsymcount = 0;
0e1862bb 2417 if (bfd_link_pic (info))
07d6d2b8
AM
2418 {
2419 asection * p;
2420 const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
c3b7224a 2421
07d6d2b8
AM
2422 for (p = output_bfd->sections; p ; p = p->next)
2423 if ((p->flags & SEC_EXCLUDE) == 0
2424 && (p->flags & SEC_ALLOC) != 0
2425 && !(*bed->elf_backend_omit_section_dynsym) (output_bfd, info, p))
2426 ++ dynsecsymcount;
2427 }
1c0d3aa6
NC
2428
2429 if (!score_elf_sort_hash_table (info, dynsecsymcount + 1))
0a1b45a2 2430 return false;
1c0d3aa6
NC
2431 }
2432
2433 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
c3b7224a 2434 extsymoff = (elf_bad_symtab (input_bfd)) ? 0 : symtab_hdr->sh_info;
1c0d3aa6
NC
2435 rel = relocs;
2436 relend = relocs + input_section->reloc_count;
2437 for (; rel < relend; rel++)
2438 {
2439 int r_type;
2440 reloc_howto_type *howto;
2441 unsigned long r_symndx;
2442 Elf_Internal_Sym *sym;
2443 asection *sec;
2444 struct score_elf_link_hash_entry *h;
2445 bfd_vma relocation = 0;
2446 bfd_reloc_status_type r;
2447 arelent bfd_reloc;
2448
2449 r_symndx = ELF32_R_SYM (rel->r_info);
2450 r_type = ELF32_R_TYPE (rel->r_info);
2451
f3185997
NC
2452 if (! s3_bfd_score_info_to_howto (input_bfd, &bfd_reloc, (Elf_Internal_Rela *) rel))
2453 continue;
1c0d3aa6
NC
2454 howto = bfd_reloc.howto;
2455
1c0d3aa6
NC
2456 h = NULL;
2457 sym = NULL;
2458 sec = NULL;
2459
2460 if (r_symndx < extsymoff)
07d6d2b8
AM
2461 {
2462 sym = local_syms + r_symndx;
2463 sec = local_sections[r_symndx];
2464 relocation = (sec->output_section->vma
2465 + sec->output_offset
2466 + sym->st_value);
2467 name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec);
2468
2469 if (!bfd_link_relocatable (info)
2470 && (sec->flags & SEC_MERGE)
2471 && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
2472 {
2473 asection *msec;
2474 bfd_vma addend, value;
2475
2476 switch (r_type)
2477 {
2478 case R_SCORE_HI16:
2479 break;
2480 case R_SCORE_LO16:
2481 hi16_addend = score_bfd_get_32 (input_bfd, contents + rel->r_offset - 4);
2482 hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1;
2483 value = score_bfd_get_32 (input_bfd, contents + rel->r_offset);
2484 offset = ((((value >> 16) & 0x3) << 15) | (value & 0x7fff)) >> 1;
2485 addend = (hi16_offset << 16) | (offset & 0xffff);
2486 msec = sec;
2487 addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
2488 addend -= relocation;
2489 addend += msec->output_section->vma + msec->output_offset;
2490 uvalue = addend;
2491 hi16_offset = (uvalue >> 16) << 1;
2492 hi16_value = (hi16_addend & (~(howto->dst_mask)))
2493 | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
2494 score_bfd_put_32 (input_bfd, hi16_value, contents + rel->r_offset - 4);
2495 offset = (uvalue & 0xffff) << 1;
2496 value = (value & (~(howto->dst_mask)))
2497 | (offset & 0x7fff) | ((offset << 1) & 0x30000);
2498 score_bfd_put_32 (input_bfd, value, contents + rel->r_offset);
2499 break;
2500
2501 case R_SCORE_IMM32:
2502 {
2503 value = score_bfd_get_48 (input_bfd, contents + rel->r_offset);
2504 addend = ((value >> 5) & 0x3ff)
2505 | (((value >> 16) & 0x7fff) << 10)
2506 | (((value >> 32) & 0x7f) << 25);
2507 msec = sec;
2508 addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
2509 addend -= relocation;
2510 addend += msec->output_section->vma + msec->output_offset;
2511 addend &= 0xffffffff;
2512 value = (value & ~howto->src_mask)
2513 | ((addend & 0x3ff) << 5)
2514 | (((addend >> 10) & 0x7fff) << 16)
2515 | (((addend >> 25) & 0x7f) << 32);
2516 score_bfd_put_48 (input_bfd, value, contents + rel->r_offset);
2517 break;
2518 }
2519
2520 case R_SCORE_IMM30:
2521 {
2522 int not_word_align_p = 0;
2523 value = score_bfd_get_48 (input_bfd, contents + rel->r_offset);
2524 addend = ((value >> 7) & 0xff)
2525 | (((value >> 16) & 0x7fff) << 8)
2526 | (((value >> 32) & 0x7f) << 23);
2527 addend <<= howto->rightshift;
2528 msec = sec;
2529 addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
2530 addend -= relocation;
2531 addend += msec->output_section->vma + msec->output_offset;
2532 addend &= 0xffffffff;
2533
2534 /* Check lw48/sw48 rd, value/label word align. */
2535 if ((addend & 0x3) != 0)
2536 not_word_align_p = 1;
2537
2538 addend >>= howto->rightshift;
2539 value = (value & ~howto->src_mask)
2540 | (((addend & 0xff) >> 0) << 7)
2541 | (((addend & 0x7fff00) >> 8) << 16)
2542 | (((addend & 0x3f800000) >> 23) << 32);
2543 score_bfd_put_48 (input_bfd, value, contents + rel->r_offset);
2544
2545 if (not_word_align_p)
2546 return bfd_reloc_other;
2547 else
2548 break;
2549 }
2550
2551 case R_SCORE_GOT_LO16:
2552 value = score_bfd_get_32 (input_bfd, contents + rel->r_offset);
2553 addend = (((value >> 16) & 0x3) << 14) | ((value & 0x7fff) >> 1);
2554 msec = sec;
2555 addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
2556 addend += msec->output_section->vma + msec->output_offset;
2557 value = (value & (~(howto->dst_mask))) | ((addend & 0x3fff) << 1)
2558 | (((addend >> 14) & 0x3) << 16);
2559
2560 score_bfd_put_32 (input_bfd, value, contents + rel->r_offset);
2561 break;
2562
2563 case R_SCORE_ABS32:
2564 case R_SCORE_REL32:
2565 value = bfd_get_32 (input_bfd, contents + rel->r_offset);
2566 /* Get the (signed) value from the instruction. */
2567 addend = value & howto->src_mask;
2568 if (addend & ((howto->src_mask + 1) >> 1))
2569 {
2570 bfd_signed_vma mask;
2571
2572 mask = -1;
2573 mask &= ~howto->src_mask;
2574 addend |= mask;
2575 }
2576 msec = sec;
2577 addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
2578 addend += msec->output_section->vma + msec->output_offset;
2579 value = (value & ~howto->dst_mask) | (addend & howto->dst_mask);
2580 bfd_put_32 (input_bfd, value, contents + rel->r_offset);
2581 break;
2582
2583 default:
2584 value = score_bfd_get_32 (input_bfd, contents + rel->r_offset);
2585 /* Get the (signed) value from the instruction. */
2586 addend = value & howto->src_mask;
2587 if (addend & ((howto->src_mask + 1) >> 1))
2588 {
2589 bfd_signed_vma mask;
2590
2591 mask = -1;
2592 mask &= ~howto->src_mask;
2593 addend |= mask;
2594 }
2595 msec = sec;
2596 addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
2597 addend += msec->output_section->vma + msec->output_offset;
2598 value = (value & ~howto->dst_mask) | (addend & howto->dst_mask);
2599 score_bfd_put_32 (input_bfd, value, contents + rel->r_offset);
2600 break;
2601 }
2602 }
2603 }
1c0d3aa6 2604 else
07d6d2b8
AM
2605 {
2606 /* For global symbols we look up the symbol in the hash-table. */
2607 h = ((struct score_elf_link_hash_entry *)
2608 elf_sym_hashes (input_bfd) [r_symndx - extsymoff]);
8a5da09b
AM
2609
2610 if (info->wrap_hash != NULL
2611 && (input_section->flags & SEC_DEBUGGING) != 0)
2612 h = ((struct score_elf_link_hash_entry *)
2613 unwrap_hash_lookup (info, input_bfd, &h->root.root));
2614
07d6d2b8
AM
2615 /* Find the real hash-table entry for this symbol. */
2616 while (h->root.root.type == bfd_link_hash_indirect
2617 || h->root.root.type == bfd_link_hash_warning)
2618 h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link;
2619
2620 /* Record the name of this symbol, for our caller. */
2621 name = h->root.root.root.string;
2622
2623 /* See if this is the special GP_DISP_LABEL symbol. Note that such a
2624 symbol must always be a global symbol. */
2625 if (strcmp (name, GP_DISP_LABEL) == 0)
2626 {
2627 /* Relocations against GP_DISP_LABEL are permitted only with
2628 R_SCORE_HI16 and R_SCORE_LO16 relocations. */
2629 if (r_type != R_SCORE_HI16 && r_type != R_SCORE_LO16)
2630 return bfd_reloc_notsupported;
2631
0a1b45a2 2632 gp_disp_p = true;
07d6d2b8
AM
2633 }
2634
2635 /* If this symbol is defined, calculate its address. Note that
2636 GP_DISP_LABEL is a magic symbol, always implicitly defined by the
2637 linker, so it's inappropriate to check to see whether or not
2638 its defined. */
2639 else if ((h->root.root.type == bfd_link_hash_defined
2640 || h->root.root.type == bfd_link_hash_defweak)
2641 && h->root.root.u.def.section)
2642 {
2643 sec = h->root.root.u.def.section;
2644 if (sec->output_section)
2645 relocation = (h->root.root.u.def.value
2646 + sec->output_section->vma
2647 + sec->output_offset);
2648 else
2649 {
2650 relocation = h->root.root.u.def.value;
2651 }
2652 }
2653 else if (h->root.root.type == bfd_link_hash_undefweak)
2654 /* We allow relocations against undefined weak symbols, giving
2655 it the value zero, so that you can undefined weak functions
2656 and check to see if they exist by looking at their addresses. */
2657 relocation = 0;
2658 else if (info->unresolved_syms_in_objects == RM_IGNORE
2659 && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
2660 relocation = 0;
2661 else if (strcmp (name, "_DYNAMIC_LINK") == 0)
2662 {
2663 /* If this is a dynamic link, we should have created a _DYNAMIC_LINK symbol
2664 in s3_bfd_score_elf_create_dynamic_sections. Otherwise, we should define
2665 the symbol with a value of 0. */
2666 BFD_ASSERT (! bfd_link_pic (info));
2667 BFD_ASSERT (bfd_get_section_by_name (output_bfd, ".dynamic") == NULL);
2668 relocation = 0;
2669 }
2670 else if (!bfd_link_relocatable (info))
2671 {
95a51568
FS
2672 info->callbacks->undefined_symbol
2673 (info, h->root.root.root.string, input_bfd, input_section,
2674 rel->r_offset,
2675 (info->unresolved_syms_in_objects == RM_DIAGNOSE
2676 && !info->warn_unresolved_syms)
1a72702b 2677 || ELF_ST_VISIBILITY (h->root.other));
95a51568
FS
2678 relocation = 0;
2679 }
07d6d2b8 2680 }
1c0d3aa6 2681
dbaa2011 2682 if (sec != NULL && discarded_section (sec))
e4067dbb 2683 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
545fd46b 2684 rel, 1, relend, howto, 0, contents);
ab96bf03 2685
0e1862bb 2686 if (bfd_link_relocatable (info))
07d6d2b8
AM
2687 {
2688 /* This is a relocatable link. We don't have to change
2689 anything, unless the reloc is against a section symbol,
2690 in which case we have to adjust according to where the
2691 section symbol winds up in the output section. */
2692 if (r_symndx < symtab_hdr->sh_info)
2693 {
2694 sym = local_syms + r_symndx;
2695 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
2696 {
2697 sec = local_sections[r_symndx];
2698 score_elf_add_to_rel (input_bfd, contents + rel->r_offset,
2699 howto, (bfd_signed_vma) (sec->output_offset + sym->st_value));
2700 }
2701 }
2702 continue;
2703 }
ab96bf03 2704
c3b7224a 2705 /* This is a final link. */
1c0d3aa6 2706 r = score_elf_final_link_relocate (howto, input_bfd, output_bfd,
07d6d2b8
AM
2707 input_section, contents, rel, relocs,
2708 relocation, info, name,
2709 (h ? ELF_ST_TYPE ((unsigned int)h->root.root.type) :
2710 ELF_ST_TYPE ((unsigned int)sym->st_info)), h, local_sections,
2711 gp_disp_p);
1c0d3aa6
NC
2712
2713 if (r != bfd_reloc_ok)
07d6d2b8
AM
2714 {
2715 const char *msg = (const char *)0;
2716
2717 switch (r)
2718 {
2719 case bfd_reloc_overflow:
2720 /* If the overflowing reloc was to an undefined symbol,
2721 we have already printed one error message and there
2722 is no point complaining again. */
1a72702b
AM
2723 if (!h || h->root.root.type != bfd_link_hash_undefined)
2724 (*info->callbacks->reloc_overflow)
2725 (info, NULL, name, howto->name, (bfd_vma) 0,
2726 input_bfd, input_section, rel->r_offset);
07d6d2b8
AM
2727 break;
2728 case bfd_reloc_undefined:
1a72702b 2729 (*info->callbacks->undefined_symbol)
0a1b45a2 2730 (info, name, input_bfd, input_section, rel->r_offset, true);
07d6d2b8 2731 break;
1c0d3aa6 2732
07d6d2b8
AM
2733 case bfd_reloc_outofrange:
2734 msg = _("internal error: out of range error");
2735 goto common_error;
1c0d3aa6 2736
07d6d2b8
AM
2737 case bfd_reloc_notsupported:
2738 msg = _("internal error: unsupported relocation error");
2739 goto common_error;
1c0d3aa6 2740
07d6d2b8
AM
2741 case bfd_reloc_dangerous:
2742 msg = _("internal error: dangerous error");
2743 goto common_error;
1c0d3aa6 2744
07d6d2b8
AM
2745 /* Use bfd_reloc_other to check lw48, sw48 word align. */
2746 case bfd_reloc_other:
38f14ab8 2747 msg = _("address not word aligned");
07d6d2b8 2748 goto common_error;
c3b7224a 2749
07d6d2b8
AM
2750 default:
2751 msg = _("internal error: unknown error");
2752 /* Fall through. */
1c0d3aa6 2753
07d6d2b8 2754 common_error:
1a72702b
AM
2755 (*info->callbacks->warning) (info, msg, name, input_bfd,
2756 input_section, rel->r_offset);
07d6d2b8
AM
2757 break;
2758 }
2759 }
1c0d3aa6
NC
2760 }
2761
0a1b45a2 2762 return true;
1c0d3aa6
NC
2763}
2764
2765/* Look through the relocs for a section during the first phase, and
2766 allocate space in the global offset table. */
0a1b45a2 2767static bool
c3b7224a 2768s3_bfd_score_elf_check_relocs (bfd *abfd,
07d6d2b8
AM
2769 struct bfd_link_info *info,
2770 asection *sec,
2771 const Elf_Internal_Rela *relocs)
1c0d3aa6 2772{
1c0d3aa6
NC
2773 bfd *dynobj;
2774 Elf_Internal_Shdr *symtab_hdr;
2775 struct elf_link_hash_entry **sym_hashes;
2776 struct score_got_info *g;
2777 size_t extsymoff;
2778 const Elf_Internal_Rela *rel;
2779 const Elf_Internal_Rela *rel_end;
2780 asection *sgot;
2781 asection *sreloc;
1c0d3aa6 2782
0e1862bb 2783 if (bfd_link_relocatable (info))
0a1b45a2 2784 return true;
1c0d3aa6
NC
2785
2786 dynobj = elf_hash_table (info)->dynobj;
2787 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
2788 sym_hashes = elf_sym_hashes (abfd);
c3b7224a 2789 extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info;
1c0d3aa6 2790
1c0d3aa6
NC
2791 if (dynobj == NULL)
2792 {
2793 sgot = NULL;
2794 g = NULL;
2795 }
2796 else
2797 {
0a1b45a2 2798 sgot = score_elf_got_section (dynobj, false);
1c0d3aa6 2799 if (sgot == NULL)
07d6d2b8 2800 g = NULL;
1c0d3aa6 2801 else
07d6d2b8
AM
2802 {
2803 BFD_ASSERT (score_elf_section_data (sgot) != NULL);
2804 g = score_elf_section_data (sgot)->u.got_info;
2805 BFD_ASSERT (g != NULL);
2806 }
1c0d3aa6
NC
2807 }
2808
2809 sreloc = NULL;
056bafd4 2810 rel_end = relocs + sec->reloc_count;
1c0d3aa6
NC
2811 for (rel = relocs; rel < rel_end; ++rel)
2812 {
2813 unsigned long r_symndx;
2814 unsigned int r_type;
2815 struct elf_link_hash_entry *h;
2816
2817 r_symndx = ELF32_R_SYM (rel->r_info);
2818 r_type = ELF32_R_TYPE (rel->r_info);
2819
2820 if (r_symndx < extsymoff)
07d6d2b8
AM
2821 {
2822 h = NULL;
2823 }
1c0d3aa6 2824 else if (r_symndx >= extsymoff + NUM_SHDR_ENTRIES (symtab_hdr))
07d6d2b8 2825 {
4eca0228 2826 _bfd_error_handler
695344c0 2827 /* xgettext:c-format */
38f14ab8 2828 (_("%pB: malformed reloc detected for section %pA"), abfd, sec);
07d6d2b8 2829 bfd_set_error (bfd_error_bad_value);
0a1b45a2 2830 return false;
07d6d2b8 2831 }
1c0d3aa6 2832 else
07d6d2b8
AM
2833 {
2834 h = sym_hashes[r_symndx - extsymoff];
1c0d3aa6 2835
07d6d2b8
AM
2836 /* This may be an indirect symbol created because of a version. */
2837 if (h != NULL)
2838 {
2839 while (h->root.type == bfd_link_hash_indirect)
2840 h = (struct elf_link_hash_entry *)h->root.u.i.link;
2841 }
2842 }
1c0d3aa6
NC
2843
2844 /* Some relocs require a global offset table. */
2845 if (dynobj == NULL || sgot == NULL)
07d6d2b8
AM
2846 {
2847 switch (r_type)
2848 {
2849 case R_SCORE_GOT15:
2850 case R_SCORE_CALL15:
2851 if (dynobj == NULL)
2852 elf_hash_table (info)->dynobj = dynobj = abfd;
0a1b45a2
AM
2853 if (!score_elf_create_got_section (dynobj, info, false))
2854 return false;
07d6d2b8
AM
2855 g = score_elf_got_info (dynobj, &sgot);
2856 break;
2857 case R_SCORE_ABS32:
2858 case R_SCORE_REL32:
2859 if (dynobj == NULL
0e1862bb
L
2860 && (bfd_link_pic (info) || h != NULL)
2861 && (sec->flags & SEC_ALLOC) != 0)
07d6d2b8
AM
2862 elf_hash_table (info)->dynobj = dynobj = abfd;
2863 break;
2864 default:
2865 break;
2866 }
2867 }
1c0d3aa6
NC
2868
2869 if (!h && (r_type == R_SCORE_GOT_LO16))
07d6d2b8
AM
2870 {
2871 if (! score_elf_record_local_got_symbol (abfd, r_symndx, rel->r_addend, g))
0a1b45a2 2872 return false;
07d6d2b8 2873 }
1c0d3aa6
NC
2874
2875 switch (r_type)
07d6d2b8
AM
2876 {
2877 case R_SCORE_CALL15:
2878 if (h == NULL)
2879 {
4eca0228 2880 _bfd_error_handler
695344c0 2881 /* xgettext:c-format */
2dcf00ce
AM
2882 (_("%pB: CALL15 reloc at %#" PRIx64 " not against global symbol"),
2883 abfd, (uint64_t) rel->r_offset);
07d6d2b8 2884 bfd_set_error (bfd_error_bad_value);
0a1b45a2 2885 return false;
07d6d2b8
AM
2886 }
2887 else
2888 {
2889 /* This symbol requires a global offset table entry. */
2890 if (! score_elf_record_global_got_symbol (h, abfd, info, g))
0a1b45a2 2891 return false;
07d6d2b8
AM
2892
2893 /* We need a stub, not a plt entry for the undefined function. But we record
2894 it as if it needs plt. See _bfd_elf_adjust_dynamic_symbol. */
2895 h->needs_plt = 1;
2896 h->type = STT_FUNC;
2897 }
2898 break;
2899 case R_SCORE_GOT15:
2900 if (h && ! score_elf_record_global_got_symbol (h, abfd, info, g))
0a1b45a2 2901 return false;
07d6d2b8
AM
2902 break;
2903 case R_SCORE_ABS32:
2904 case R_SCORE_REL32:
2905 if ((bfd_link_pic (info) || h != NULL)
0e1862bb 2906 && (sec->flags & SEC_ALLOC) != 0)
07d6d2b8
AM
2907 {
2908 if (sreloc == NULL)
2909 {
0a1b45a2 2910 sreloc = score_elf_rel_dyn_section (dynobj, true);
07d6d2b8 2911 if (sreloc == NULL)
0a1b45a2 2912 return false;
07d6d2b8 2913 }
1c0d3aa6 2914#define SCORE_READONLY_SECTION (SEC_ALLOC | SEC_LOAD | SEC_READONLY)
07d6d2b8
AM
2915 if (bfd_link_pic (info))
2916 {
2917 /* When creating a shared object, we must copy these reloc types into
2918 the output file as R_SCORE_REL32 relocs. We make room for this reloc
2919 in the .rel.dyn reloc section. */
2920 score_elf_allocate_dynamic_relocations (dynobj, 1);
2921 if ((sec->flags & SCORE_READONLY_SECTION)
2922 == SCORE_READONLY_SECTION)
2923 /* We tell the dynamic linker that there are
2924 relocations against the text segment. */
2925 info->flags |= DF_TEXTREL;
2926 }
2927 else
2928 {
2929 struct score_elf_link_hash_entry *hscore;
2930
2931 /* We only need to copy this reloc if the symbol is
2932 defined in a dynamic object. */
2933 hscore = (struct score_elf_link_hash_entry *)h;
2934 ++hscore->possibly_dynamic_relocs;
2935 if ((sec->flags & SCORE_READONLY_SECTION)
2936 == SCORE_READONLY_SECTION)
2937 /* We need it to tell the dynamic linker if there
2938 are relocations against the text segment. */
0a1b45a2 2939 hscore->readonly_reloc = true;
07d6d2b8
AM
2940 }
2941
2942 /* Even though we don't directly need a GOT entry for this symbol,
2943 a symbol must have a dynamic symbol table index greater that
2944 DT_SCORE_GOTSYM if there are dynamic relocations against it. */
2945 if (h != NULL)
2946 {
2947 if (dynobj == NULL)
2948 elf_hash_table (info)->dynobj = dynobj = abfd;
0a1b45a2
AM
2949 if (! score_elf_create_got_section (dynobj, info, true))
2950 return false;
07d6d2b8
AM
2951 g = score_elf_got_info (dynobj, &sgot);
2952 if (! score_elf_record_global_got_symbol (h, abfd, info, g))
0a1b45a2 2953 return false;
07d6d2b8
AM
2954 }
2955 }
2956 break;
2957
2958 /* This relocation describes the C++ object vtable hierarchy.
2959 Reconstruct it for later use during GC. */
2960 case R_SCORE_GNU_VTINHERIT:
2961 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
0a1b45a2 2962 return false;
07d6d2b8
AM
2963 break;
2964
2965 /* This relocation describes which C++ vtable entries are actually
2966 used. Record for later use during GC. */
2967 case R_SCORE_GNU_VTENTRY:
2968 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
0a1b45a2 2969 return false;
07d6d2b8
AM
2970 break;
2971 default:
2972 break;
2973 }
1c0d3aa6
NC
2974
2975 /* We must not create a stub for a symbol that has relocations
07d6d2b8 2976 related to taking the function's address. */
1c0d3aa6 2977 switch (r_type)
07d6d2b8
AM
2978 {
2979 default:
2980 if (h != NULL)
2981 {
2982 struct score_elf_link_hash_entry *sh;
2983
2984 sh = (struct score_elf_link_hash_entry *) h;
0a1b45a2 2985 sh->no_fn_stub = true;
07d6d2b8
AM
2986 }
2987 break;
2988 case R_SCORE_CALL15:
2989 break;
2990 }
1c0d3aa6
NC
2991 }
2992
0a1b45a2 2993 return true;
1c0d3aa6
NC
2994}
2995
0a1b45a2 2996static bool
c3b7224a 2997s3_bfd_score_elf_add_symbol_hook (bfd *abfd,
07d6d2b8
AM
2998 struct bfd_link_info *info ATTRIBUTE_UNUSED,
2999 Elf_Internal_Sym *sym,
3000 const char **namep ATTRIBUTE_UNUSED,
3001 flagword *flagsp ATTRIBUTE_UNUSED,
3002 asection **secp,
3003 bfd_vma *valp)
1c0d3aa6
NC
3004{
3005 switch (sym->st_shndx)
3006 {
3007 case SHN_COMMON:
3008 if (sym->st_size > elf_gp_size (abfd))
07d6d2b8 3009 break;
1c0d3aa6
NC
3010 /* Fall through. */
3011 case SHN_SCORE_SCOMMON:
3012 *secp = bfd_make_section_old_way (abfd, ".scommon");
10885e24 3013 (*secp)->flags |= SEC_IS_COMMON | SEC_SMALL_DATA;
1c0d3aa6
NC
3014 *valp = sym->st_size;
3015 break;
3016 }
3017
0a1b45a2 3018 return true;
1c0d3aa6
NC
3019}
3020
3021static void
c3b7224a 3022s3_bfd_score_elf_symbol_processing (bfd *abfd, asymbol *asym)
1c0d3aa6
NC
3023{
3024 elf_symbol_type *elfsym;
3025
3026 elfsym = (elf_symbol_type *) asym;
3027 switch (elfsym->internal_elf_sym.st_shndx)
3028 {
3029 case SHN_COMMON:
3030 if (asym->value > elf_gp_size (abfd))
07d6d2b8 3031 break;
1c0d3aa6
NC
3032 /* Fall through. */
3033 case SHN_SCORE_SCOMMON:
1c0d3aa6
NC
3034 asym->section = &score_elf_scom_section;
3035 asym->value = elfsym->internal_elf_sym.st_size;
3036 break;
3037 }
3038}
3039
6e0b88f1 3040static int
c3b7224a 3041s3_bfd_score_elf_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED,
07d6d2b8
AM
3042 const char *name ATTRIBUTE_UNUSED,
3043 Elf_Internal_Sym *sym,
3044 asection *input_sec,
3045 struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
1c0d3aa6
NC
3046{
3047 /* If we see a common symbol, which implies a relocatable link, then
3048 if a symbol was small common in an input file, mark it as small
3049 common in the output file. */
3050 if (sym->st_shndx == SHN_COMMON && strcmp (input_sec->name, ".scommon") == 0)
3051 sym->st_shndx = SHN_SCORE_SCOMMON;
3052
6e0b88f1 3053 return 1;
1c0d3aa6
NC
3054}
3055
0a1b45a2 3056static bool
c3b7224a 3057s3_bfd_score_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
07d6d2b8
AM
3058 asection *sec,
3059 int *retval)
1c0d3aa6 3060{
fd361982 3061 if (strcmp (bfd_section_name (sec), ".scommon") == 0)
1c0d3aa6
NC
3062 {
3063 *retval = SHN_SCORE_SCOMMON;
0a1b45a2 3064 return true;
1c0d3aa6
NC
3065 }
3066
0a1b45a2 3067 return false;
1c0d3aa6
NC
3068}
3069
3070/* Adjust a symbol defined by a dynamic object and referenced by a
3071 regular object. The current definition is in some section of the
3072 dynamic object, but we're not including those sections. We have to
3073 change the definition to something the rest of the link can understand. */
0a1b45a2 3074static bool
c3b7224a 3075s3_bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
07d6d2b8 3076 struct elf_link_hash_entry *h)
1c0d3aa6
NC
3077{
3078 bfd *dynobj;
3079 struct score_elf_link_hash_entry *hscore;
3080 asection *s;
3081
3082 dynobj = elf_hash_table (info)->dynobj;
3083
3084 /* Make sure we know what is going on here. */
3085 BFD_ASSERT (dynobj != NULL
07d6d2b8
AM
3086 && (h->needs_plt
3087 || h->is_weakalias
3088 || (h->def_dynamic && h->ref_regular && !h->def_regular)));
1c0d3aa6
NC
3089
3090 /* If this symbol is defined in a dynamic object, we need to copy
3091 any R_SCORE_ABS32 or R_SCORE_REL32 relocs against it into the output
3092 file. */
3093 hscore = (struct score_elf_link_hash_entry *)h;
0e1862bb 3094 if (!bfd_link_relocatable (info)
1c0d3aa6
NC
3095 && hscore->possibly_dynamic_relocs != 0
3096 && (h->root.type == bfd_link_hash_defweak || !h->def_regular))
3097 {
3098 score_elf_allocate_dynamic_relocations (dynobj, hscore->possibly_dynamic_relocs);
3099 if (hscore->readonly_reloc)
07d6d2b8
AM
3100 /* We tell the dynamic linker that there are relocations
3101 against the text segment. */
3102 info->flags |= DF_TEXTREL;
1c0d3aa6
NC
3103 }
3104
3105 /* For a function, create a stub, if allowed. */
3106 if (!hscore->no_fn_stub && h->needs_plt)
3107 {
3108 if (!elf_hash_table (info)->dynamic_sections_created)
0a1b45a2 3109 return true;
1c0d3aa6
NC
3110
3111 /* If this symbol is not defined in a regular file, then set
07d6d2b8
AM
3112 the symbol to the stub location. This is required to make
3113 function pointers compare as equal between the normal
3114 executable and the shared library. */
1c0d3aa6 3115 if (!h->def_regular)
07d6d2b8
AM
3116 {
3117 /* We need .stub section. */
3118 s = bfd_get_linker_section (dynobj, SCORE_ELF_STUB_SECTION_NAME);
3119 BFD_ASSERT (s != NULL);
1c0d3aa6 3120
07d6d2b8
AM
3121 h->root.u.def.section = s;
3122 h->root.u.def.value = s->size;
1c0d3aa6 3123
07d6d2b8
AM
3124 /* XXX Write this stub address somewhere. */
3125 h->plt.offset = s->size;
1c0d3aa6 3126
07d6d2b8
AM
3127 /* Make room for this stub code. */
3128 s->size += SCORE_FUNCTION_STUB_SIZE;
1c0d3aa6 3129
07d6d2b8
AM
3130 /* The last half word of the stub will be filled with the index
3131 of this symbol in .dynsym section. */
0a1b45a2 3132 return true;
07d6d2b8 3133 }
1c0d3aa6
NC
3134 }
3135 else if ((h->type == STT_FUNC) && !h->needs_plt)
3136 {
3137 /* This will set the entry for this symbol in the GOT to 0, and
07d6d2b8 3138 the dynamic linker will take care of this. */
1c0d3aa6 3139 h->root.u.def.value = 0;
0a1b45a2 3140 return true;
1c0d3aa6
NC
3141 }
3142
3143 /* If this is a weak symbol, and there is a real definition, the
3144 processor independent code will have arranged for us to see the
3145 real definition first, and we can just use the same value. */
60d67dc8 3146 if (h->is_weakalias)
1c0d3aa6 3147 {
60d67dc8
AM
3148 struct elf_link_hash_entry *def = weakdef (h);
3149 BFD_ASSERT (def->root.type == bfd_link_hash_defined);
3150 h->root.u.def.section = def->root.u.def.section;
3151 h->root.u.def.value = def->root.u.def.value;
0a1b45a2 3152 return true;
1c0d3aa6
NC
3153 }
3154
3155 /* This is a reference to a symbol defined by a dynamic object which
3156 is not a function. */
0a1b45a2 3157 return true;
1c0d3aa6
NC
3158}
3159
3160/* This function is called after all the input files have been read,
3161 and the input sections have been assigned to output sections. */
0a1b45a2 3162static bool
af969b14
AM
3163s3_bfd_score_elf_early_size_sections (bfd *output_bfd,
3164 struct bfd_link_info *info)
1c0d3aa6
NC
3165{
3166 bfd *dynobj;
3167 asection *s;
3168 struct score_got_info *g;
3169 int i;
3170 bfd_size_type loadable_size = 0;
3171 bfd_size_type local_gotno;
3172 bfd *sub;
3173
3174 dynobj = elf_hash_table (info)->dynobj;
3175 if (dynobj == NULL)
3176 /* Relocatable links don't have it. */
0a1b45a2 3177 return true;
1c0d3aa6
NC
3178
3179 g = score_elf_got_info (dynobj, &s);
3180 if (s == NULL)
0a1b45a2 3181 return true;
1c0d3aa6
NC
3182
3183 /* Calculate the total loadable size of the output. That will give us the
3184 maximum number of GOT_PAGE entries required. */
c72f2fb2 3185 for (sub = info->input_bfds; sub; sub = sub->link.next)
1c0d3aa6
NC
3186 {
3187 asection *subsection;
3188
3189 for (subsection = sub->sections;
07d6d2b8
AM
3190 subsection;
3191 subsection = subsection->next)
3192 {
3193 if ((subsection->flags & SEC_ALLOC) == 0)
3194 continue;
3195 loadable_size += ((subsection->size + 0xf)
3196 &~ (bfd_size_type) 0xf);
3197 }
1c0d3aa6
NC
3198 }
3199
3200 /* There has to be a global GOT entry for every symbol with
3201 a dynamic symbol table index of DT_SCORE_GOTSYM or
3202 higher. Therefore, it make sense to put those symbols
3203 that need GOT entries at the end of the symbol table. We
3204 do that here. */
3205 if (! score_elf_sort_hash_table (info, 1))
0a1b45a2 3206 return false;
1c0d3aa6
NC
3207
3208 if (g->global_gotsym != NULL)
3209 i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx;
3210 else
3211 /* If there are no global symbols, or none requiring
3212 relocations, then GLOBAL_GOTSYM will be NULL. */
3213 i = 0;
3214
3215 /* In the worst case, we'll get one stub per dynamic symbol. */
3216 loadable_size += SCORE_FUNCTION_STUB_SIZE * i;
3217
3218 /* Assume there are two loadable segments consisting of
3219 contiguous sections. Is 5 enough? */
3220 local_gotno = (loadable_size >> 16) + 5;
3221
3222 g->local_gotno += local_gotno;
3223 s->size += g->local_gotno * SCORE_ELF_GOT_SIZE (output_bfd);
3224
3225 g->global_gotno = i;
3226 s->size += i * SCORE_ELF_GOT_SIZE (output_bfd);
3227
3228 score_elf_resolve_final_got_entries (g);
3229
3230 if (s->size > SCORE_ELF_GOT_MAX_SIZE (output_bfd))
3231 {
3232 /* Fixme. Error message or Warning message should be issued here. */
3233 }
3234
0a1b45a2 3235 return true;
1c0d3aa6
NC
3236}
3237
3238/* Set the sizes of the dynamic sections. */
0a1b45a2 3239static bool
af969b14 3240s3_bfd_score_elf_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
1c0d3aa6
NC
3241{
3242 bfd *dynobj;
3243 asection *s;
0a1b45a2 3244 bool reltext;
1c0d3aa6
NC
3245
3246 dynobj = elf_hash_table (info)->dynobj;
af969b14
AM
3247 if (dynobj == NULL)
3248 return true;
1c0d3aa6
NC
3249
3250 if (elf_hash_table (info)->dynamic_sections_created)
3251 {
3252 /* Set the contents of the .interp section to the interpreter. */
f5233a16 3253 if (bfd_link_executable (info) && !info->nointerp)
07d6d2b8
AM
3254 {
3255 s = bfd_get_linker_section (dynobj, ".interp");
3256 BFD_ASSERT (s != NULL);
3257 s->size = strlen (ELF_DYNAMIC_INTERPRETER) + 1;
3258 s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
3259 }
1c0d3aa6
NC
3260 }
3261
3262 /* The check_relocs and adjust_dynamic_symbol entry points have
3263 determined the sizes of the various dynamic sections. Allocate
3264 memory for them. */
0a1b45a2 3265 reltext = false;
1c0d3aa6
NC
3266 for (s = dynobj->sections; s != NULL; s = s->next)
3267 {
3268 const char *name;
3269
3270 if ((s->flags & SEC_LINKER_CREATED) == 0)
07d6d2b8 3271 continue;
1c0d3aa6
NC
3272
3273 /* It's OK to base decisions on the section name, because none
07d6d2b8 3274 of the dynobj section names depend upon the input files. */
fd361982 3275 name = bfd_section_name (s);
1c0d3aa6 3276
08dedd66 3277 if (startswith (name, ".rel"))
07d6d2b8
AM
3278 {
3279 if (s->size == 0)
3280 {
3281 /* We only strip the section if the output section name
3282 has the same name. Otherwise, there might be several
3283 input sections for this output section. FIXME: This
3284 code is probably not needed these days anyhow, since
3285 the linker now does not create empty output sections. */
3286 if (s->output_section != NULL
3287 && strcmp (name,
fd361982 3288 bfd_section_name (s->output_section)) == 0)
07d6d2b8
AM
3289 s->flags |= SEC_EXCLUDE;
3290 }
3291 else
3292 {
3293 const char *outname;
3294 asection *target;
3295
3296 /* If this relocation section applies to a read only
3297 section, then we probably need a DT_TEXTREL entry.
3298 If the relocation section is .rel.dyn, we always
3299 assert a DT_TEXTREL entry rather than testing whether
3300 there exists a relocation to a read only section or
3301 not. */
fd361982 3302 outname = bfd_section_name (s->output_section);
07d6d2b8
AM
3303 target = bfd_get_section_by_name (output_bfd, outname + 4);
3304 if ((target != NULL
3305 && (target->flags & SEC_READONLY) != 0
3306 && (target->flags & SEC_ALLOC) != 0) || strcmp (outname, ".rel.dyn") == 0)
0a1b45a2 3307 reltext = true;
07d6d2b8
AM
3308
3309 /* We use the reloc_count field as a counter if we need
3310 to copy relocs into the output file. */
3311 if (strcmp (name, ".rel.dyn") != 0)
3312 s->reloc_count = 0;
3313 }
3314 }
08dedd66 3315 else if (startswith (name, ".got"))
07d6d2b8 3316 {
af969b14 3317 /* s3_bfd_score_elf_early_size_sections() has already done
07d6d2b8
AM
3318 most of the work, but some symbols may have been mapped
3319 to versions that we must now resolve in the got_entries
3320 hash tables. */
3321 }
1c0d3aa6 3322 else if (strcmp (name, SCORE_ELF_STUB_SECTION_NAME) == 0)
07d6d2b8
AM
3323 {
3324 /* IRIX rld assumes that the function stub isn't at the end
3325 of .text section. So put a dummy. XXX */
3326 s->size += SCORE_FUNCTION_STUB_SIZE;
3327 }
08dedd66 3328 else if (! startswith (name, ".init"))
07d6d2b8
AM
3329 {
3330 /* It's not one of our sections, so don't allocate space. */
3331 continue;
3332 }
1c0d3aa6
NC
3333
3334 /* Allocate memory for the section contents. */
3335 s->contents = bfd_zalloc (dynobj, s->size);
3336 if (s->contents == NULL && s->size != 0)
07d6d2b8
AM
3337 {
3338 bfd_set_error (bfd_error_no_memory);
0a1b45a2 3339 return false;
07d6d2b8 3340 }
1c0d3aa6
NC
3341 }
3342
3343 if (elf_hash_table (info)->dynamic_sections_created)
3344 {
3345 /* Add some entries to the .dynamic section. We fill in the
07d6d2b8
AM
3346 values later, in s3_bfd_score_elf_finish_dynamic_sections, but we
3347 must add the entries now so that we get the correct size for
3348 the .dynamic section. The DT_DEBUG entry is filled in by the
3349 dynamic linker and used by the debugger. */
1c0d3aa6
NC
3350
3351 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_DEBUG, 0))
0a1b45a2 3352 return false;
1c0d3aa6
NC
3353
3354 if (reltext)
07d6d2b8 3355 info->flags |= DF_TEXTREL;
1c0d3aa6
NC
3356
3357 if ((info->flags & DF_TEXTREL) != 0)
07d6d2b8
AM
3358 {
3359 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_TEXTREL, 0))
0a1b45a2 3360 return false;
07d6d2b8 3361 }
1c0d3aa6
NC
3362
3363 if (! SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0))
0a1b45a2 3364 return false;
1c0d3aa6 3365
0a1b45a2 3366 if (score_elf_rel_dyn_section (dynobj, false))
07d6d2b8
AM
3367 {
3368 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0))
0a1b45a2 3369 return false;
1c0d3aa6 3370
07d6d2b8 3371 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELSZ, 0))
0a1b45a2 3372 return false;
1c0d3aa6 3373
07d6d2b8 3374 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELENT, 0))
0a1b45a2 3375 return false;
07d6d2b8 3376 }
1c0d3aa6
NC
3377
3378 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_BASE_ADDRESS, 0))
0a1b45a2 3379 return false;
1c0d3aa6
NC
3380
3381 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_LOCAL_GOTNO, 0))
0a1b45a2 3382 return false;
1c0d3aa6
NC
3383
3384 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_SYMTABNO, 0))
0a1b45a2 3385 return false;
1c0d3aa6
NC
3386
3387 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_UNREFEXTNO, 0))
0a1b45a2 3388 return false;
1c0d3aa6
NC
3389
3390 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_GOTSYM, 0))
0a1b45a2 3391 return false;
1c0d3aa6
NC
3392
3393 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_HIPAGENO, 0))
0a1b45a2 3394 return false;
1c0d3aa6
NC
3395 }
3396
0a1b45a2 3397 return true;
1c0d3aa6
NC
3398}
3399
0a1b45a2 3400static bool
c3b7224a 3401s3_bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
1c0d3aa6
NC
3402{
3403 struct elf_link_hash_entry *h;
3404 struct bfd_link_hash_entry *bh;
3405 flagword flags;
3406 asection *s;
3407
3408 flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
07d6d2b8 3409 | SEC_LINKER_CREATED | SEC_READONLY);
1c0d3aa6
NC
3410
3411 /* ABI requests the .dynamic section to be read only. */
3d4d4302 3412 s = bfd_get_linker_section (abfd, ".dynamic");
1c0d3aa6
NC
3413 if (s != NULL)
3414 {
fd361982 3415 if (!bfd_set_section_flags (s, flags))
0a1b45a2 3416 return false;
1c0d3aa6
NC
3417 }
3418
3419 /* We need to create .got section. */
0a1b45a2
AM
3420 if (!score_elf_create_got_section (abfd, info, false))
3421 return false;
1c0d3aa6 3422
0a1b45a2
AM
3423 if (!score_elf_rel_dyn_section (elf_hash_table (info)->dynobj, true))
3424 return false;
1c0d3aa6
NC
3425
3426 /* Create .stub section. */
3d4d4302 3427 if (bfd_get_linker_section (abfd, SCORE_ELF_STUB_SECTION_NAME) == NULL)
1c0d3aa6 3428 {
3d4d4302
AM
3429 s = bfd_make_section_anyway_with_flags (abfd, SCORE_ELF_STUB_SECTION_NAME,
3430 flags | SEC_CODE);
1c0d3aa6 3431 if (s == NULL
fd361982 3432 || !bfd_set_section_alignment (s, 2))
1c0d3aa6 3433
0a1b45a2 3434 return false;
1c0d3aa6
NC
3435 }
3436
0e1862bb 3437 if (!bfd_link_pic (info))
1c0d3aa6
NC
3438 {
3439 const char *name;
3440
3441 name = "_DYNAMIC_LINK";
3442 bh = NULL;
3443 if (!(_bfd_generic_link_add_one_symbol
07d6d2b8 3444 (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr,
0a1b45a2
AM
3445 (bfd_vma) 0, NULL, false, get_elf_backend_data (abfd)->collect, &bh)))
3446 return false;
1c0d3aa6
NC
3447
3448 h = (struct elf_link_hash_entry *)bh;
3449 h->non_elf = 0;
3450 h->def_regular = 1;
3451 h->type = STT_SECTION;
3452
3453 if (!bfd_elf_link_record_dynamic_symbol (info, h))
0a1b45a2 3454 return false;
1c0d3aa6
NC
3455 }
3456
0a1b45a2 3457 return true;
1c0d3aa6
NC
3458}
3459
3460
3461/* Finish up dynamic symbol handling. We set the contents of various
3462 dynamic sections here. */
0a1b45a2 3463static bool
c3b7224a 3464s3_bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd,
07d6d2b8
AM
3465 struct bfd_link_info *info,
3466 struct elf_link_hash_entry *h,
3467 Elf_Internal_Sym *sym)
1c0d3aa6
NC
3468{
3469 bfd *dynobj;
3470 asection *sgot;
3471 struct score_got_info *g;
3472 const char *name;
3473
3474 dynobj = elf_hash_table (info)->dynobj;
3475
3476 if (h->plt.offset != MINUS_ONE)
3477 {
3478 asection *s;
3479 bfd_byte stub[SCORE_FUNCTION_STUB_SIZE];
3480
3481 /* This symbol has a stub. Set it up. */
3482 BFD_ASSERT (h->dynindx != -1);
3483
3d4d4302 3484 s = bfd_get_linker_section (dynobj, SCORE_ELF_STUB_SECTION_NAME);
1c0d3aa6
NC
3485 BFD_ASSERT (s != NULL);
3486
3487 /* FIXME: Can h->dynindex be more than 64K? */
3488 if (h->dynindx & 0xffff0000)
cf95b909
AM
3489 {
3490 _bfd_error_handler
3491 (_("%pB: cannot handle more than %d dynamic symbols"),
3492 output_bfd, 0xffff);
3493 bfd_set_error (bfd_error_bad_value);
3494 return false;
3495 }
1c0d3aa6
NC
3496
3497 /* Fill the stub. */
c3b7224a
NC
3498 score_bfd_put_32 (output_bfd, STUB_LW, stub);
3499 score_bfd_put_32 (output_bfd, STUB_MOVE, stub + 4);
3500 score_bfd_put_32 (output_bfd, STUB_LI16 | (h->dynindx << 1), stub + 8);
3501 score_bfd_put_32 (output_bfd, STUB_BRL, stub + 12);
1c0d3aa6
NC
3502
3503 BFD_ASSERT (h->plt.offset <= s->size);
3504 memcpy (s->contents + h->plt.offset, stub, SCORE_FUNCTION_STUB_SIZE);
3505
3506 /* Mark the symbol as undefined. plt.offset != -1 occurs
07d6d2b8 3507 only for the referenced symbol. */
1c0d3aa6
NC
3508 sym->st_shndx = SHN_UNDEF;
3509
3510 /* The run-time linker uses the st_value field of the symbol
07d6d2b8
AM
3511 to reset the global offset table entry for this external
3512 to its stub address when unlinking a shared object. */
1c0d3aa6
NC
3513 sym->st_value = (s->output_section->vma + s->output_offset + h->plt.offset);
3514 }
3515
3516 BFD_ASSERT (h->dynindx != -1 || h->forced_local);
3517
0a1b45a2 3518 sgot = score_elf_got_section (dynobj, false);
1c0d3aa6
NC
3519 BFD_ASSERT (sgot != NULL);
3520 BFD_ASSERT (score_elf_section_data (sgot) != NULL);
3521 g = score_elf_section_data (sgot)->u.got_info;
3522 BFD_ASSERT (g != NULL);
3523
3524 /* Run through the global symbol table, creating GOT entries for all
3525 the symbols that need them. */
3526 if (g->global_gotsym != NULL && h->dynindx >= g->global_gotsym->dynindx)
3527 {
3528 bfd_vma offset;
3529 bfd_vma value;
3530
3531 value = sym->st_value;
3532 offset = score_elf_global_got_index (dynobj, h);
c3b7224a 3533 score_bfd_put_32 (output_bfd, value, sgot->contents + offset);
1c0d3aa6
NC
3534 }
3535
3536 /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
3537 name = h->root.root.string;
9637f6ef
L
3538 if (h == elf_hash_table (info)->hdynamic
3539 || h == elf_hash_table (info)->hgot)
1c0d3aa6
NC
3540 sym->st_shndx = SHN_ABS;
3541 else if (strcmp (name, "_DYNAMIC_LINK") == 0)
3542 {
3543 sym->st_shndx = SHN_ABS;
3544 sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
3545 sym->st_value = 1;
3546 }
3547 else if (strcmp (name, GP_DISP_LABEL) == 0)
3548 {
3549 sym->st_shndx = SHN_ABS;
3550 sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
3551 sym->st_value = elf_gp (output_bfd);
3552 }
3553
0a1b45a2 3554 return true;
1c0d3aa6
NC
3555}
3556
3557/* Finish up the dynamic sections. */
0a1b45a2 3558static bool
c3b7224a 3559s3_bfd_score_elf_finish_dynamic_sections (bfd *output_bfd,
07d6d2b8 3560 struct bfd_link_info *info)
1c0d3aa6
NC
3561{
3562 bfd *dynobj;
3563 asection *sdyn;
3564 asection *sgot;
3565 asection *s;
3566 struct score_got_info *g;
3567
3568 dynobj = elf_hash_table (info)->dynobj;
3569
3d4d4302 3570 sdyn = bfd_get_linker_section (dynobj, ".dynamic");
1c0d3aa6 3571
0a1b45a2 3572 sgot = score_elf_got_section (dynobj, false);
1c0d3aa6
NC
3573 if (sgot == NULL)
3574 g = NULL;
3575 else
3576 {
3577 BFD_ASSERT (score_elf_section_data (sgot) != NULL);
3578 g = score_elf_section_data (sgot)->u.got_info;
3579 BFD_ASSERT (g != NULL);
3580 }
3581
3582 if (elf_hash_table (info)->dynamic_sections_created)
3583 {
3584 bfd_byte *b;
3585
3586 BFD_ASSERT (sdyn != NULL);
3587 BFD_ASSERT (g != NULL);
3588
3589 for (b = sdyn->contents;
07d6d2b8
AM
3590 b < sdyn->contents + sdyn->size;
3591 b += SCORE_ELF_DYN_SIZE (dynobj))
3592 {
3593 Elf_Internal_Dyn dyn;
3594 const char *name;
3595 size_t elemsize;
0a1b45a2 3596 bool swap_out_p;
07d6d2b8
AM
3597
3598 /* Read in the current dynamic entry. */
3599 (*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn);
3600
3601 /* Assume that we're going to modify it and write it out. */
0a1b45a2 3602 swap_out_p = true;
07d6d2b8
AM
3603
3604 switch (dyn.d_tag)
3605 {
3606 case DT_RELENT:
3607 dyn.d_un.d_val = SCORE_ELF_REL_SIZE (dynobj);
3608 break;
3609
3610 case DT_STRSZ:
3611 /* Rewrite DT_STRSZ. */
3612 dyn.d_un.d_val
3613 = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
3614 break;
3615
3616 case DT_PLTGOT:
3617 s = elf_hash_table (info)->sgot;
3618 dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
3619 break;
3620
3621 case DT_SCORE_BASE_ADDRESS:
3622 s = output_bfd->sections;
3623 BFD_ASSERT (s != NULL);
3624 dyn.d_un.d_ptr = s->vma & ~(bfd_vma) 0xffff;
3625 break;
3626
3627 case DT_SCORE_LOCAL_GOTNO:
3628 dyn.d_un.d_val = g->local_gotno;
3629 break;
3630
3631 case DT_SCORE_UNREFEXTNO:
3632 /* The index into the dynamic symbol table which is the
3633 entry of the first external symbol that is not
3634 referenced within the same object. */
3635 dyn.d_un.d_val = bfd_count_sections (output_bfd) + 1;
3636 break;
3637
3638 case DT_SCORE_GOTSYM:
3639 if (g->global_gotsym)
3640 {
3641 dyn.d_un.d_val = g->global_gotsym->dynindx;
3642 break;
3643 }
3644 /* In case if we don't have global got symbols we default
3645 to setting DT_SCORE_GOTSYM to the same value as
3646 DT_SCORE_SYMTABNO. */
1a0670f3 3647 /* Fall through. */
c3b7224a 3648
07d6d2b8
AM
3649 case DT_SCORE_SYMTABNO:
3650 name = ".dynsym";
3651 elemsize = SCORE_ELF_SYM_SIZE (output_bfd);
3652 s = bfd_get_linker_section (dynobj, name);
3653 dyn.d_un.d_val = s->size / elemsize;
3654 break;
3655
3656 case DT_SCORE_HIPAGENO:
3657 dyn.d_un.d_val = g->local_gotno - SCORE_RESERVED_GOTNO;
3658 break;
3659
3660 default:
0a1b45a2 3661 swap_out_p = false;
07d6d2b8
AM
3662 break;
3663 }
3664
3665 if (swap_out_p)
3666 (*get_elf_backend_data (dynobj)->s->swap_dyn_out) (dynobj, &dyn, b);
3667 }
1c0d3aa6
NC
3668 }
3669
3670 /* The first entry of the global offset table will be filled at
3671 runtime. The second entry will be used by some runtime loaders.
3672 This isn't the case of IRIX rld. */
3673 if (sgot != NULL && sgot->size > 0)
3674 {
c3b7224a
NC
3675 score_bfd_put_32 (output_bfd, 0, sgot->contents);
3676 score_bfd_put_32 (output_bfd, 0x80000000, sgot->contents + SCORE_ELF_GOT_SIZE (output_bfd));
1c0d3aa6
NC
3677 }
3678
3679 if (sgot != NULL)
3680 elf_section_data (sgot->output_section)->this_hdr.sh_entsize
3681 = SCORE_ELF_GOT_SIZE (output_bfd);
3682
3683
3684 /* We need to sort the entries of the dynamic relocation section. */
0a1b45a2 3685 s = score_elf_rel_dyn_section (dynobj, false);
1c0d3aa6
NC
3686
3687 if (s != NULL && s->size > (bfd_vma)2 * SCORE_ELF_REL_SIZE (output_bfd))
3688 {
3689 reldyn_sorting_bfd = output_bfd;
3690 qsort ((Elf32_External_Rel *) s->contents + 1, s->reloc_count - 1,
07d6d2b8 3691 sizeof (Elf32_External_Rel), score_elf_sort_dynamic_relocs);
1c0d3aa6
NC
3692 }
3693
0a1b45a2 3694 return true;
1c0d3aa6
NC
3695}
3696
3697/* This function set up the ELF section header for a BFD section in preparation for writing
3698 it out. This is where the flags and type fields are set for unusual sections. */
0a1b45a2 3699static bool
c3b7224a 3700s3_bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
07d6d2b8
AM
3701 Elf_Internal_Shdr *hdr,
3702 asection *sec)
1c0d3aa6
NC
3703{
3704 const char *name;
3705
fd361982 3706 name = bfd_section_name (sec);
1c0d3aa6
NC
3707
3708 if (strcmp (name, ".got") == 0
3709 || strcmp (name, ".srdata") == 0
3710 || strcmp (name, ".sdata") == 0
3711 || strcmp (name, ".sbss") == 0)
3712 hdr->sh_flags |= SHF_SCORE_GPREL;
3713
0a1b45a2 3714 return true;
1c0d3aa6
NC
3715}
3716
3717/* This function do additional processing on the ELF section header before writing
3718 it out. This is used to set the flags and type fields for some sections. */
3719
3720/* assign_file_positions_except_relocs() check section flag and if it is allocatable,
3721 warning message will be issued. backend_fake_section is called before
3722 assign_file_positions_except_relocs(); backend_section_processing after it. so, we
3723 modify section flag there, but not backend_fake_section. */
0a1b45a2 3724static bool
c3b7224a 3725s3_bfd_score_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr)
1c0d3aa6
NC
3726{
3727 if (hdr->bfd_section != NULL)
3728 {
fd361982 3729 const char *name = bfd_section_name (hdr->bfd_section);
1c0d3aa6
NC
3730
3731 if (strcmp (name, ".sdata") == 0)
07d6d2b8
AM
3732 {
3733 hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_SCORE_GPREL;
3734 hdr->sh_type = SHT_PROGBITS;
3735 }
1c0d3aa6 3736 else if (strcmp (name, ".sbss") == 0)
07d6d2b8
AM
3737 {
3738 hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_SCORE_GPREL;
3739 hdr->sh_type = SHT_NOBITS;
3740 }
1c0d3aa6 3741 else if (strcmp (name, ".srdata") == 0)
07d6d2b8
AM
3742 {
3743 hdr->sh_flags |= SHF_ALLOC | SHF_SCORE_GPREL;
3744 hdr->sh_type = SHT_PROGBITS;
3745 }
1c0d3aa6
NC
3746 }
3747
0a1b45a2 3748 return true;
1c0d3aa6
NC
3749}
3750
0a1b45a2 3751static bool
c3b7224a 3752s3_bfd_score_elf_write_section (bfd *output_bfd, asection *sec, bfd_byte *contents)
1c0d3aa6
NC
3753{
3754 bfd_byte *to, *from, *end;
3755 int i;
3756
3757 if (strcmp (sec->name, ".pdr") != 0)
0a1b45a2 3758 return false;
1c0d3aa6
NC
3759
3760 if (score_elf_section_data (sec)->u.tdata == NULL)
0a1b45a2 3761 return false;
1c0d3aa6
NC
3762
3763 to = contents;
3764 end = contents + sec->size;
3765 for (from = contents, i = 0; from < end; from += PDR_SIZE, i++)
3766 {
3767 if ((score_elf_section_data (sec)->u.tdata)[i] == 1)
07d6d2b8 3768 continue;
1c0d3aa6
NC
3769
3770 if (to != from)
07d6d2b8 3771 memcpy (to, from, PDR_SIZE);
1c0d3aa6
NC
3772
3773 to += PDR_SIZE;
3774 }
3775 bfd_set_section_contents (output_bfd, sec->output_section, contents,
07d6d2b8 3776 (file_ptr) sec->output_offset, sec->size);
1c0d3aa6 3777
0a1b45a2 3778 return true;
1c0d3aa6
NC
3779}
3780
3781/* Copy data from a SCORE ELF indirect symbol to its direct symbol, hiding the old
3782 indirect symbol. Process additional relocation information. */
1c0d3aa6 3783static void
c3b7224a 3784s3_bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info,
07d6d2b8
AM
3785 struct elf_link_hash_entry *dir,
3786 struct elf_link_hash_entry *ind)
1c0d3aa6
NC
3787{
3788 struct score_elf_link_hash_entry *dirscore, *indscore;
3789
3790 _bfd_elf_link_hash_copy_indirect (info, dir, ind);
3791
3792 if (ind->root.type != bfd_link_hash_indirect)
3793 return;
3794
3795 dirscore = (struct score_elf_link_hash_entry *) dir;
3796 indscore = (struct score_elf_link_hash_entry *) ind;
3797 dirscore->possibly_dynamic_relocs += indscore->possibly_dynamic_relocs;
3798
3799 if (indscore->readonly_reloc)
0a1b45a2 3800 dirscore->readonly_reloc = true;
1c0d3aa6
NC
3801
3802 if (indscore->no_fn_stub)
0a1b45a2 3803 dirscore->no_fn_stub = true;
1c0d3aa6
NC
3804}
3805
3806/* Remove information about discarded functions from other sections which mention them. */
0a1b45a2 3807static bool
c3b7224a 3808s3_bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie,
07d6d2b8 3809 struct bfd_link_info *info)
1c0d3aa6
NC
3810{
3811 asection *o;
0a1b45a2 3812 bool ret = false;
1c0d3aa6
NC
3813 unsigned char *tdata;
3814 size_t i, skip;
3815
3816 o = bfd_get_section_by_name (abfd, ".pdr");
3817 if ((!o) || (o->size == 0) || (o->size % PDR_SIZE != 0)
3818 || (o->output_section != NULL && bfd_is_abs_section (o->output_section)))
0a1b45a2 3819 return false;
1c0d3aa6
NC
3820
3821 tdata = bfd_zmalloc (o->size / PDR_SIZE);
3822 if (!tdata)
0a1b45a2 3823 return false;
1c0d3aa6
NC
3824
3825 cookie->rels = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, info->keep_memory);
3826 if (!cookie->rels)
3827 {
3828 free (tdata);
0a1b45a2 3829 return false;
1c0d3aa6
NC
3830 }
3831
3832 cookie->rel = cookie->rels;
3833 cookie->relend = cookie->rels + o->reloc_count;
3834
3835 for (i = 0, skip = 0; i < o->size; i++)
3836 {
3837 if (bfd_elf_reloc_symbol_deleted_p (i * PDR_SIZE, cookie))
07d6d2b8
AM
3838 {
3839 tdata[i] = 1;
3840 skip++;
3841 }
1c0d3aa6
NC
3842 }
3843
3844 if (skip != 0)
3845 {
3846 score_elf_section_data (o)->u.tdata = tdata;
3847 o->size -= skip * PDR_SIZE;
0a1b45a2 3848 ret = true;
1c0d3aa6
NC
3849 }
3850 else
3851 free (tdata);
3852
3853 if (!info->keep_memory)
3854 free (cookie->rels);
3855
3856 return ret;
3857}
3858
3859/* Signal that discard_info() has removed the discarded relocations for this section. */
0a1b45a2 3860static bool
c3b7224a 3861s3_bfd_score_elf_ignore_discarded_relocs (asection *sec)
1c0d3aa6
NC
3862{
3863 if (strcmp (sec->name, ".pdr") == 0)
0a1b45a2
AM
3864 return true;
3865 return false;
1c0d3aa6
NC
3866}
3867
07adf181
AM
3868/* Return the section that should be marked against GC for a given
3869 relocation. */
1c0d3aa6 3870static asection *
c3b7224a 3871s3_bfd_score_elf_gc_mark_hook (asection *sec,
07d6d2b8
AM
3872 struct bfd_link_info *info,
3873 Elf_Internal_Rela *rel,
3874 struct elf_link_hash_entry *h,
3875 Elf_Internal_Sym *sym)
1c0d3aa6
NC
3876{
3877 if (h != NULL)
07adf181
AM
3878 switch (ELF32_R_TYPE (rel->r_info))
3879 {
3880 case R_SCORE_GNU_VTINHERIT:
3881 case R_SCORE_GNU_VTENTRY:
07d6d2b8 3882 return NULL;
07adf181 3883 }
1c0d3aa6 3884
07adf181 3885 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
1c0d3aa6
NC
3886}
3887
3888/* Support for core dump NOTE sections. */
3889
0a1b45a2 3890static bool
c3b7224a 3891s3_bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
1c0d3aa6
NC
3892{
3893 int offset;
3894 unsigned int raw_size;
3895
3896 switch (note->descsz)
3897 {
3898 default:
0a1b45a2 3899 return false;
1c0d3aa6 3900
07d6d2b8 3901 case 148: /* Linux/Score 32-bit. */
1c0d3aa6 3902 /* pr_cursig */
228e534f
AM
3903 elf_tdata (abfd)->core->signal
3904 = score_bfd_get_16 (abfd, note->descdata + 12);
1c0d3aa6
NC
3905
3906 /* pr_pid */
228e534f
AM
3907 elf_tdata (abfd)->core->lwpid
3908 = score_bfd_get_32 (abfd, note->descdata + 24);
1c0d3aa6
NC
3909
3910 /* pr_reg */
3911 offset = 72;
3912 raw_size = 72;
3913
3914 break;
3915 }
3916
3917 /* Make a ".reg/999" section. */
228e534f
AM
3918 return _bfd_elfcore_make_pseudosection (abfd, ".reg", raw_size,
3919 note->descpos + offset);
1c0d3aa6
NC
3920}
3921
0a1b45a2 3922static bool
c3b7224a 3923s3_bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
1c0d3aa6
NC
3924{
3925 switch (note->descsz)
3926 {
3927 default:
0a1b45a2 3928 return false;
1c0d3aa6 3929
07d6d2b8 3930 case 124: /* Linux/Score elf_prpsinfo. */
228e534f
AM
3931 elf_tdata (abfd)->core->program
3932 = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16);
3933 elf_tdata (abfd)->core->command
3934 = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80);
1c0d3aa6
NC
3935 }
3936
3937 /* Note that for some reason, a spurious space is tacked
3938 onto the end of the args in some (at least one anyway)
3939 implementations, so strip it off if it exists. */
3940
3941 {
228e534f 3942 char *command = elf_tdata (abfd)->core->command;
1c0d3aa6
NC
3943 int n = strlen (command);
3944
3945 if (0 < n && command[n - 1] == ' ')
3946 command[n - 1] = '\0';
3947 }
3948
0a1b45a2 3949 return true;
1c0d3aa6
NC
3950}
3951
3952
3953/* Score BFD functions. */
1c0d3aa6 3954static reloc_howto_type *
c3b7224a 3955s3_elf32_score_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
1c0d3aa6
NC
3956{
3957 unsigned int i;
3958
c3b7224a 3959 for (i = 0; i < ARRAY_SIZE (elf32_score_reloc_map); i++)
1c0d3aa6
NC
3960 if (elf32_score_reloc_map[i].bfd_reloc_val == code)
3961 return &elf32_score_howto_table[elf32_score_reloc_map[i].elf_reloc_val];
3962
3963 return NULL;
3964}
3965
157090f7
AM
3966static reloc_howto_type *
3967elf32_score_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
07d6d2b8 3968 const char *r_name)
157090f7
AM
3969{
3970 unsigned int i;
3971
3972 for (i = 0;
3973 i < (sizeof (elf32_score_howto_table)
07d6d2b8 3974 / sizeof (elf32_score_howto_table[0]));
157090f7
AM
3975 i++)
3976 if (elf32_score_howto_table[i].name != NULL
07d6d2b8 3977 && strcasecmp (elf32_score_howto_table[i].name, r_name) == 0)
157090f7
AM
3978 return &elf32_score_howto_table[i];
3979
3980 return NULL;
3981}
3982
0a1b45a2 3983static bool
c3b7224a 3984s3_elf32_score_print_private_bfd_data (bfd *abfd, void * ptr)
1c0d3aa6
NC
3985{
3986 FILE *file = (FILE *) ptr;
3987
3988 BFD_ASSERT (abfd != NULL && ptr != NULL);
3989
3990 /* Print normal ELF private data. */
3991 _bfd_elf_print_private_bfd_data (abfd, ptr);
3992
3993 /* xgettext:c-format */
3994 fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
3995 if (elf_elfheader (abfd)->e_flags & EF_SCORE_PIC)
3996 {
3997 fprintf (file, _(" [pic]"));
3998 }
3999 if (elf_elfheader (abfd)->e_flags & EF_SCORE_FIXDEP)
4000 {
4001 fprintf (file, _(" [fix dep]"));
4002 }
4003 fputc ('\n', file);
4004
0a1b45a2 4005 return true;
1c0d3aa6
NC
4006}
4007
0a1b45a2 4008static bool
50e03d47 4009s3_elf32_score_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
1c0d3aa6 4010{
50e03d47 4011 bfd *obfd = info->output_bfd;
1c0d3aa6
NC
4012 flagword in_flags;
4013 flagword out_flags;
4014
50e03d47 4015 if (!_bfd_generic_verify_endian_match (ibfd, info))
0a1b45a2 4016 return false;
1c0d3aa6 4017
6b728d32
AM
4018 /* FIXME: What should be checked when linking shared libraries? */
4019 if ((ibfd->flags & DYNAMIC) != 0)
0a1b45a2 4020 return true;
6b728d32 4021
1c0d3aa6
NC
4022 in_flags = elf_elfheader (ibfd)->e_flags;
4023 out_flags = elf_elfheader (obfd)->e_flags;
4024
4025 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
4026 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
0a1b45a2 4027 return true;
1c0d3aa6
NC
4028
4029 in_flags = elf_elfheader (ibfd)->e_flags;
4030 out_flags = elf_elfheader (obfd)->e_flags;
4031
4032 if (! elf_flags_init (obfd))
4033 {
0a1b45a2 4034 elf_flags_init (obfd) = true;
1c0d3aa6
NC
4035 elf_elfheader (obfd)->e_flags = in_flags;
4036
4037 if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
07d6d2b8
AM
4038 && bfd_get_arch_info (obfd)->the_default)
4039 {
4040 return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
4041 }
1c0d3aa6 4042
0a1b45a2 4043 return true;
1c0d3aa6
NC
4044 }
4045
4046 if (((in_flags & EF_SCORE_PIC) != 0) != ((out_flags & EF_SCORE_PIC) != 0))
4eca0228 4047 _bfd_error_handler
871b3ab2 4048 (_("%pB: warning: linking PIC files with non-PIC files"), ibfd);
1c0d3aa6
NC
4049
4050 /* FIXME: Maybe dependency fix compatibility should be checked here. */
4051
0a1b45a2 4052 return true;
1c0d3aa6
NC
4053}
4054
0a1b45a2 4055static bool
c3b7224a 4056s3_elf32_score_new_section_hook (bfd *abfd, asection *sec)
1c0d3aa6
NC
4057{
4058 struct _score_elf_section_data *sdata;
986f0783 4059 size_t amt = sizeof (*sdata);
1c0d3aa6
NC
4060
4061 sdata = bfd_zalloc (abfd, amt);
4062 if (sdata == NULL)
0a1b45a2 4063 return false;
1c0d3aa6
NC
4064 sec->used_by_bfd = sdata;
4065
4066 return _bfd_elf_new_section_hook (abfd, sec);
4067}
4068
c3b7224a
NC
4069/*****************************************************************************/
4070
4071/* s3_s7: backend hooks. */
0a1b45a2 4072static bool
c3b7224a 4073_bfd_score_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
07d6d2b8
AM
4074 arelent *bfd_reloc,
4075 Elf_Internal_Rela *elf_reloc)
c3b7224a
NC
4076{
4077 if (bfd_get_mach (abfd) == bfd_mach_score3)
4078 return s3_bfd_score_info_to_howto (abfd, bfd_reloc, elf_reloc);
4079 else
4080 return s7_bfd_score_info_to_howto (abfd, bfd_reloc, elf_reloc);
4081}
4082
0f684201 4083static int
c3b7224a 4084_bfd_score_elf_relocate_section (bfd *output_bfd,
07d6d2b8
AM
4085 struct bfd_link_info *info,
4086 bfd *input_bfd,
4087 asection *input_section,
4088 bfd_byte *contents,
4089 Elf_Internal_Rela *relocs,
4090 Elf_Internal_Sym *local_syms,
4091 asection **local_sections)
c3b7224a
NC
4092{
4093 if (bfd_get_mach (output_bfd) == bfd_mach_score3)
4094 return s3_bfd_score_elf_relocate_section (output_bfd,
07d6d2b8
AM
4095 info, input_bfd, input_section, contents, relocs,
4096 local_syms, local_sections);
c3b7224a
NC
4097 else
4098 return s7_bfd_score_elf_relocate_section (output_bfd,
07d6d2b8
AM
4099 info, input_bfd, input_section, contents, relocs,
4100 local_syms, local_sections);
c3b7224a
NC
4101}
4102
0a1b45a2 4103static bool
c3b7224a 4104_bfd_score_elf_check_relocs (bfd *abfd,
07d6d2b8
AM
4105 struct bfd_link_info *info,
4106 asection *sec,
4107 const Elf_Internal_Rela *relocs)
c3b7224a
NC
4108{
4109 if (bfd_get_mach (abfd) == bfd_mach_score3)
4110 return s3_bfd_score_elf_check_relocs (abfd, info, sec, relocs);
4111 else
4112 return s7_bfd_score_elf_check_relocs (abfd, info, sec, relocs);
4113}
4114
0a1b45a2 4115static bool
c3b7224a 4116_bfd_score_elf_add_symbol_hook (bfd *abfd,
07d6d2b8
AM
4117 struct bfd_link_info *info ATTRIBUTE_UNUSED,
4118 Elf_Internal_Sym *sym,
4119 const char **namep ATTRIBUTE_UNUSED,
4120 flagword *flagsp ATTRIBUTE_UNUSED,
4121 asection **secp,
4122 bfd_vma *valp)
c3b7224a
NC
4123{
4124 if (bfd_get_mach (abfd) == bfd_mach_score3)
4125 return s3_bfd_score_elf_add_symbol_hook (abfd, info, sym, namep, flagsp,
07d6d2b8 4126 secp, valp);
c3b7224a
NC
4127 else
4128 return s7_bfd_score_elf_add_symbol_hook (abfd, info, sym, namep, flagsp,
07d6d2b8 4129 secp, valp);
c3b7224a
NC
4130}
4131
4132static void
4133_bfd_score_elf_symbol_processing (bfd *abfd, asymbol *asym)
4134{
4135 if (bfd_get_mach (abfd) == bfd_mach_score3)
4136 return s3_bfd_score_elf_symbol_processing (abfd, asym);
4137 else
4138 return s7_bfd_score_elf_symbol_processing (abfd, asym);
4139}
4140
6e0b88f1 4141static int
c3b7224a
NC
4142_bfd_score_elf_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED,
4143 const char *name ATTRIBUTE_UNUSED,
4144 Elf_Internal_Sym *sym,
4145 asection *input_sec,
4146 struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
4147{
4148 /* If link a empty .o, then this filed is NULL. */
4149 if (info->input_bfds == NULL)
4150 {
4151 /* If we see a common symbol, which implies a relocatable link, then
07d6d2b8
AM
4152 if a symbol was small common in an input file, mark it as small
4153 common in the output file. */
c3b7224a 4154 if (sym->st_shndx == SHN_COMMON && strcmp (input_sec->name, ".scommon") == 0)
07d6d2b8 4155 sym->st_shndx = SHN_SCORE_SCOMMON;
6e0b88f1 4156 return 1;
c3b7224a
NC
4157 }
4158
4159 if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
4160 return s3_bfd_score_elf_link_output_symbol_hook (info, name, sym, input_sec, h);
4161 else
4162 return s7_bfd_score_elf_link_output_symbol_hook (info, name, sym, input_sec, h);
4163}
4164
0a1b45a2 4165static bool
c3b7224a 4166_bfd_score_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
07d6d2b8
AM
4167 asection *sec,
4168 int *retval)
c3b7224a
NC
4169{
4170 if (bfd_get_mach (abfd) == bfd_mach_score3)
4171 return s3_bfd_score_elf_section_from_bfd_section (abfd, sec, retval);
4172 else
4173 return s7_bfd_score_elf_section_from_bfd_section (abfd, sec, retval);
4174}
4175
0a1b45a2 4176static bool
c3b7224a 4177_bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
07d6d2b8 4178 struct elf_link_hash_entry *h)
c3b7224a
NC
4179{
4180 if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
4181 return s3_bfd_score_elf_adjust_dynamic_symbol (info, h);
4182 else
4183 return s7_bfd_score_elf_adjust_dynamic_symbol (info, h);
4184}
4185
0a1b45a2 4186static bool
af969b14
AM
4187_bfd_score_elf_early_size_sections (bfd *output_bfd,
4188 struct bfd_link_info *info)
c3b7224a
NC
4189{
4190 if (bfd_get_mach (output_bfd) == bfd_mach_score3)
af969b14 4191 return s3_bfd_score_elf_early_size_sections (output_bfd, info);
c3b7224a 4192 else
af969b14 4193 return s7_bfd_score_elf_early_size_sections (output_bfd, info);
c3b7224a
NC
4194}
4195
0a1b45a2 4196static bool
af969b14 4197_bfd_score_elf_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
c3b7224a
NC
4198{
4199 if (bfd_get_mach (output_bfd) == bfd_mach_score3)
af969b14 4200 return s3_bfd_score_elf_late_size_sections (output_bfd, info);
c3b7224a 4201 else
af969b14 4202 return s7_bfd_score_elf_late_size_sections (output_bfd, info);
c3b7224a
NC
4203}
4204
0a1b45a2 4205static bool
c3b7224a
NC
4206_bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
4207{
4208 if (bfd_get_mach (abfd) == bfd_mach_score3)
4209 return s3_bfd_score_elf_create_dynamic_sections (abfd, info);
4210 else
4211 return s7_bfd_score_elf_create_dynamic_sections (abfd, info);
4212}
4213
0a1b45a2 4214static bool
c3b7224a 4215_bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd,
07d6d2b8
AM
4216 struct bfd_link_info *info,
4217 struct elf_link_hash_entry *h,
4218 Elf_Internal_Sym *sym)
c3b7224a
NC
4219{
4220 if (bfd_get_mach (output_bfd) == bfd_mach_score3)
4221 return s3_bfd_score_elf_finish_dynamic_symbol (output_bfd, info, h, sym);
4222 else
4223 return s7_bfd_score_elf_finish_dynamic_symbol (output_bfd, info, h, sym);
4224}
4225
0a1b45a2 4226static bool
c3b7224a 4227_bfd_score_elf_finish_dynamic_sections (bfd *output_bfd,
07d6d2b8 4228 struct bfd_link_info *info)
c3b7224a
NC
4229{
4230 if (bfd_get_mach (output_bfd) == bfd_mach_score3)
4231 return s3_bfd_score_elf_finish_dynamic_sections (output_bfd, info);
4232 else
4233 return s7_bfd_score_elf_finish_dynamic_sections (output_bfd, info);
4234}
4235
0a1b45a2 4236static bool
c3b7224a 4237_bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
07d6d2b8
AM
4238 Elf_Internal_Shdr *hdr,
4239 asection *sec)
c3b7224a
NC
4240{
4241 if (bfd_get_mach (abfd) == bfd_mach_score3)
4242 return s3_bfd_score_elf_fake_sections (abfd, hdr, sec);
4243 else
4244 return s7_bfd_score_elf_fake_sections (abfd, hdr, sec);
4245}
4246
0a1b45a2 4247static bool
c3b7224a
NC
4248_bfd_score_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr)
4249{
4250 if (bfd_get_mach (abfd) == bfd_mach_score3)
4251 return s3_bfd_score_elf_section_processing (abfd, hdr);
4252 else
4253 return s7_bfd_score_elf_section_processing (abfd, hdr);
4254}
4255
0a1b45a2 4256static bool
c3b7224a 4257_bfd_score_elf_write_section (bfd *output_bfd,
07d6d2b8
AM
4258 struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
4259 asection *sec, bfd_byte *contents)
c3b7224a
NC
4260{
4261 if (bfd_get_mach (output_bfd) == bfd_mach_score3)
4262 return s3_bfd_score_elf_write_section (output_bfd, sec, contents);
4263 else
4264 return s7_bfd_score_elf_write_section (output_bfd, sec, contents);
4265}
4266
4267static void
4268_bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info,
07d6d2b8
AM
4269 struct elf_link_hash_entry *dir,
4270 struct elf_link_hash_entry *ind)
c3b7224a
NC
4271{
4272 if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
4273 return s3_bfd_score_elf_copy_indirect_symbol (info, dir, ind);
4274 else
4275 return s7_bfd_score_elf_copy_indirect_symbol (info, dir, ind);
4276}
4277
4278static void
4279_bfd_score_elf_hide_symbol (struct bfd_link_info *info,
07d6d2b8 4280 struct elf_link_hash_entry *entry,
0a1b45a2 4281 bool force_local)
c3b7224a
NC
4282{
4283 if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
4284 return s3_bfd_score_elf_hide_symbol (info, entry, force_local);
4285 else
4286 return s7_bfd_score_elf_hide_symbol (info, entry, force_local);
4287}
4288
0a1b45a2 4289static bool
c3b7224a 4290_bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie,
07d6d2b8 4291 struct bfd_link_info *info)
c3b7224a
NC
4292{
4293 if (bfd_get_mach (abfd) == bfd_mach_score3)
4294 return s3_bfd_score_elf_discard_info (abfd, cookie, info);
4295 else
4296 return s7_bfd_score_elf_discard_info (abfd, cookie, info);
4297}
4298
0a1b45a2 4299static bool
c3b7224a
NC
4300_bfd_score_elf_ignore_discarded_relocs (asection *sec)
4301{
4302 if (bfd_get_mach (sec->owner) == bfd_mach_score3)
4303 return s3_bfd_score_elf_ignore_discarded_relocs (sec);
4304 else
4305 return s7_bfd_score_elf_ignore_discarded_relocs (sec);
4306}
4307
4308static asection *
4309_bfd_score_elf_gc_mark_hook (asection *sec,
07d6d2b8
AM
4310 struct bfd_link_info *info,
4311 Elf_Internal_Rela *rel,
4312 struct elf_link_hash_entry *h,
4313 Elf_Internal_Sym *sym)
c3b7224a
NC
4314{
4315 if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
4316 return s3_bfd_score_elf_gc_mark_hook (sec, info, rel, h, sym);
4317 else
4318 return s7_bfd_score_elf_gc_mark_hook (sec, info, rel, h, sym);
4319}
4320
0a1b45a2 4321static bool
c3b7224a
NC
4322_bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
4323{
4324 if (bfd_get_mach (abfd) == bfd_mach_score3)
4325 return s3_bfd_score_elf_grok_prstatus (abfd, note);
4326 else
4327 return s7_bfd_score_elf_grok_prstatus (abfd, note);
4328}
4329
0a1b45a2 4330static bool
c3b7224a
NC
4331_bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
4332{
4333 if (bfd_get_mach (abfd) == bfd_mach_score3)
4334 return s3_bfd_score_elf_grok_psinfo (abfd, note);
4335 else
4336 return s7_bfd_score_elf_grok_psinfo (abfd, note);
4337}
4338
4339static reloc_howto_type *
4340elf32_score_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
4341{
4342 /* s3: NOTE!!!
4343 gas will call elf32_score_reloc_type_lookup, and don't write elf file.
4344 So just using score3, but we don't know ld will call this or not.
4345 If so, this way can't work. */
4346
4347 if (score3)
4348 return s3_elf32_score_reloc_type_lookup (abfd, code);
4349 else
4350 return s7_elf32_score_reloc_type_lookup (abfd, code);
4351}
4352
4dfe6ac6
NC
4353/* Create a score elf linker hash table.
4354 This is a copy of _bfd_elf_link_hash_table_create() except with a
4355 different hash table entry creation function. */
4356
c3b7224a
NC
4357static struct bfd_link_hash_table *
4358elf32_score_link_hash_table_create (bfd *abfd)
4359{
4dfe6ac6 4360 struct elf_link_hash_table *ret;
986f0783 4361 size_t amt = sizeof (struct elf_link_hash_table);
4dfe6ac6 4362
7bf52ea2 4363 ret = (struct elf_link_hash_table *) bfd_zmalloc (amt);
4dfe6ac6
NC
4364 if (ret == NULL)
4365 return NULL;
4366
4367 if (!_bfd_elf_link_hash_table_init (ret, abfd, score_elf_link_hash_newfunc,
07d6d2b8 4368 sizeof (struct score_elf_link_hash_entry),
4dfe6ac6
NC
4369 GENERIC_ELF_DATA))
4370 {
4371 free (ret);
4372 return NULL;
4373 }
4374
4375 return &ret->root;
c3b7224a
NC
4376}
4377
0a1b45a2 4378static bool
c3b7224a
NC
4379elf32_score_print_private_bfd_data (bfd *abfd, void * ptr)
4380{
4381 if (bfd_get_mach (abfd) == bfd_mach_score3)
4382 return s3_elf32_score_print_private_bfd_data (abfd, ptr);
4383 else
4384 return s7_elf32_score_print_private_bfd_data (abfd, ptr);
4385}
4386
0a1b45a2 4387static bool
50e03d47 4388elf32_score_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
c3b7224a 4389{
50e03d47
AM
4390 if (bfd_get_mach (info->output_bfd) == bfd_mach_score3)
4391 return s3_elf32_score_merge_private_bfd_data (ibfd, info);
c3b7224a 4392 else
50e03d47 4393 return s7_elf32_score_merge_private_bfd_data (ibfd, info);
c3b7224a
NC
4394}
4395
0a1b45a2 4396static bool
c3b7224a
NC
4397elf32_score_new_section_hook (bfd *abfd, asection *sec)
4398{
4399 if (bfd_get_mach (abfd) == bfd_mach_score3)
4400 return s3_elf32_score_new_section_hook (abfd, sec);
4401 else
4402 return s7_elf32_score_new_section_hook (abfd, sec);
4403}
4404
4405
4406/* s3_s7: don't need to split. */
4407
4408/* Set the right machine number. */
0a1b45a2 4409static bool
c3b7224a
NC
4410_bfd_score_elf_score_object_p (bfd * abfd)
4411{
4412 int e_set = bfd_mach_score7;
4413
4414 if (elf_elfheader (abfd)->e_machine == EM_SCORE)
4415 {
4416 int e_mach = elf_elfheader (abfd)->e_flags & EF_SCORE_MACH & EF_OMIT_PIC_FIXDD;
4417 switch (e_mach)
07d6d2b8
AM
4418 {
4419 /* Set default target is score7. */
4420 default:
4421 case E_SCORE_MACH_SCORE7:
4422 e_set = bfd_mach_score7;
4423 break;
4424
4425 case E_SCORE_MACH_SCORE3:
4426 e_set = bfd_mach_score3;
4427 break;
4428 }
c3b7224a
NC
4429 }
4430
4431 return bfd_default_set_arch_mach (abfd, bfd_arch_score, e_set);
4432}
4433
0a1b45a2 4434bool
c3b7224a
NC
4435_bfd_score_elf_common_definition (Elf_Internal_Sym *sym)
4436{
4437 return (sym->st_shndx == SHN_COMMON || sym->st_shndx == SHN_SCORE_SCOMMON);
4438}
4439
4440/*****************************************************************************/
4441
1c0d3aa6 4442
07d6d2b8
AM
4443#define USE_REL 1
4444#define TARGET_LITTLE_SYM score_elf32_le_vec
4445#define TARGET_LITTLE_NAME "elf32-littlescore"
4446#define TARGET_BIG_SYM score_elf32_be_vec
4447#define TARGET_BIG_NAME "elf32-bigscore"
4448#define ELF_ARCH bfd_arch_score
4449#define ELF_MACHINE_CODE EM_SCORE
4450#define ELF_MACHINE_ALT1 EM_SCORE_OLD
4451#define ELF_MAXPAGESIZE 0x8000
4452
f3185997 4453#define elf_info_to_howto NULL
07d6d2b8
AM
4454#define elf_info_to_howto_rel _bfd_score_info_to_howto
4455#define elf_backend_relocate_section _bfd_score_elf_relocate_section
4456#define elf_backend_check_relocs _bfd_score_elf_check_relocs
4457#define elf_backend_add_symbol_hook _bfd_score_elf_add_symbol_hook
4458#define elf_backend_symbol_processing _bfd_score_elf_symbol_processing
9838404f
AM
4459#define elf_backend_link_output_symbol_hook \
4460 _bfd_score_elf_link_output_symbol_hook
4461#define elf_backend_section_from_bfd_section \
4462 _bfd_score_elf_section_from_bfd_section
4463#define elf_backend_adjust_dynamic_symbol \
4464 _bfd_score_elf_adjust_dynamic_symbol
af969b14
AM
4465#define elf_backend_early_size_sections \
4466 _bfd_score_elf_early_size_sections
4467#define elf_backend_late_size_sections \
4468 _bfd_score_elf_late_size_sections
d00dd7dc 4469#define elf_backend_omit_section_dynsym _bfd_elf_omit_section_dynsym_all
9838404f
AM
4470#define elf_backend_create_dynamic_sections \
4471 _bfd_score_elf_create_dynamic_sections
4472#define elf_backend_finish_dynamic_symbol \
4473 _bfd_score_elf_finish_dynamic_symbol
4474#define elf_backend_finish_dynamic_sections \
4475 _bfd_score_elf_finish_dynamic_sections
07d6d2b8
AM
4476#define elf_backend_fake_sections _bfd_score_elf_fake_sections
4477#define elf_backend_section_processing _bfd_score_elf_section_processing
4478#define elf_backend_write_section _bfd_score_elf_write_section
9838404f 4479#define elf_backend_copy_indirect_symbol _bfd_score_elf_copy_indirect_symbol
07d6d2b8
AM
4480#define elf_backend_hide_symbol _bfd_score_elf_hide_symbol
4481#define elf_backend_discard_info _bfd_score_elf_discard_info
9838404f
AM
4482#define elf_backend_ignore_discarded_relocs \
4483 _bfd_score_elf_ignore_discarded_relocs
07d6d2b8
AM
4484#define elf_backend_gc_mark_hook _bfd_score_elf_gc_mark_hook
4485#define elf_backend_grok_prstatus _bfd_score_elf_grok_prstatus
4486#define elf_backend_grok_psinfo _bfd_score_elf_grok_psinfo
4487#define elf_backend_can_gc_sections 1
4488#define elf_backend_want_plt_sym 0
4489#define elf_backend_got_header_size (4 * SCORE_RESERVED_GOTNO)
4490#define elf_backend_plt_header_size 0
0a1b45a2
AM
4491#define elf_backend_collect true
4492#define elf_backend_type_change_ok true
07d6d2b8
AM
4493#define elf_backend_object_p _bfd_score_elf_score_object_p
4494
4495#define bfd_elf32_bfd_reloc_type_lookup elf32_score_reloc_type_lookup
157090f7
AM
4496#define bfd_elf32_bfd_reloc_name_lookup \
4497 elf32_score_reloc_name_lookup
9838404f
AM
4498#define bfd_elf32_bfd_link_hash_table_create elf32_score_link_hash_table_create
4499#define bfd_elf32_bfd_print_private_bfd_data elf32_score_print_private_bfd_data
4500#define bfd_elf32_bfd_merge_private_bfd_data elf32_score_merge_private_bfd_data
07d6d2b8 4501#define bfd_elf32_new_section_hook elf32_score_new_section_hook
1c0d3aa6
NC
4502
4503#include "elf32-target.h"