]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/elf32-score.c
Add note about adding ChangeLog.git to src-release.sh
[thirdparty/binutils-gdb.git] / bfd / elf32-score.c
CommitLineData
1c0d3aa6 1/* 32-bit ELF support for S+core.
d87bef3a 2 Copyright (C) 2006-2023 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
c3b7224a 1092 s3_bfd_score_elf_size_dynamic_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
c3b7224a 3163s3_bfd_score_elf_always_size_sections (bfd *output_bfd,
07d6d2b8 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
c3b7224a 3240s3_bfd_score_elf_size_dynamic_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;
3247 BFD_ASSERT (dynobj != NULL);
3248
3249 if (elf_hash_table (info)->dynamic_sections_created)
3250 {
3251 /* Set the contents of the .interp section to the interpreter. */
f5233a16 3252 if (bfd_link_executable (info) && !info->nointerp)
07d6d2b8
AM
3253 {
3254 s = bfd_get_linker_section (dynobj, ".interp");
3255 BFD_ASSERT (s != NULL);
3256 s->size = strlen (ELF_DYNAMIC_INTERPRETER) + 1;
3257 s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
3258 }
1c0d3aa6
NC
3259 }
3260
3261 /* The check_relocs and adjust_dynamic_symbol entry points have
3262 determined the sizes of the various dynamic sections. Allocate
3263 memory for them. */
0a1b45a2 3264 reltext = false;
1c0d3aa6
NC
3265 for (s = dynobj->sections; s != NULL; s = s->next)
3266 {
3267 const char *name;
3268
3269 if ((s->flags & SEC_LINKER_CREATED) == 0)
07d6d2b8 3270 continue;
1c0d3aa6
NC
3271
3272 /* It's OK to base decisions on the section name, because none
07d6d2b8 3273 of the dynobj section names depend upon the input files. */
fd361982 3274 name = bfd_section_name (s);
1c0d3aa6 3275
08dedd66 3276 if (startswith (name, ".rel"))
07d6d2b8
AM
3277 {
3278 if (s->size == 0)
3279 {
3280 /* We only strip the section if the output section name
3281 has the same name. Otherwise, there might be several
3282 input sections for this output section. FIXME: This
3283 code is probably not needed these days anyhow, since
3284 the linker now does not create empty output sections. */
3285 if (s->output_section != NULL
3286 && strcmp (name,
fd361982 3287 bfd_section_name (s->output_section)) == 0)
07d6d2b8
AM
3288 s->flags |= SEC_EXCLUDE;
3289 }
3290 else
3291 {
3292 const char *outname;
3293 asection *target;
3294
3295 /* If this relocation section applies to a read only
3296 section, then we probably need a DT_TEXTREL entry.
3297 If the relocation section is .rel.dyn, we always
3298 assert a DT_TEXTREL entry rather than testing whether
3299 there exists a relocation to a read only section or
3300 not. */
fd361982 3301 outname = bfd_section_name (s->output_section);
07d6d2b8
AM
3302 target = bfd_get_section_by_name (output_bfd, outname + 4);
3303 if ((target != NULL
3304 && (target->flags & SEC_READONLY) != 0
3305 && (target->flags & SEC_ALLOC) != 0) || strcmp (outname, ".rel.dyn") == 0)
0a1b45a2 3306 reltext = true;
07d6d2b8
AM
3307
3308 /* We use the reloc_count field as a counter if we need
3309 to copy relocs into the output file. */
3310 if (strcmp (name, ".rel.dyn") != 0)
3311 s->reloc_count = 0;
3312 }
3313 }
08dedd66 3314 else if (startswith (name, ".got"))
07d6d2b8
AM
3315 {
3316 /* s3_bfd_score_elf_always_size_sections() has already done
3317 most of the work, but some symbols may have been mapped
3318 to versions that we must now resolve in the got_entries
3319 hash tables. */
3320 }
1c0d3aa6 3321 else if (strcmp (name, SCORE_ELF_STUB_SECTION_NAME) == 0)
07d6d2b8
AM
3322 {
3323 /* IRIX rld assumes that the function stub isn't at the end
3324 of .text section. So put a dummy. XXX */
3325 s->size += SCORE_FUNCTION_STUB_SIZE;
3326 }
08dedd66 3327 else if (! startswith (name, ".init"))
07d6d2b8
AM
3328 {
3329 /* It's not one of our sections, so don't allocate space. */
3330 continue;
3331 }
1c0d3aa6
NC
3332
3333 /* Allocate memory for the section contents. */
3334 s->contents = bfd_zalloc (dynobj, s->size);
3335 if (s->contents == NULL && s->size != 0)
07d6d2b8
AM
3336 {
3337 bfd_set_error (bfd_error_no_memory);
0a1b45a2 3338 return false;
07d6d2b8 3339 }
1c0d3aa6
NC
3340 }
3341
3342 if (elf_hash_table (info)->dynamic_sections_created)
3343 {
3344 /* Add some entries to the .dynamic section. We fill in the
07d6d2b8
AM
3345 values later, in s3_bfd_score_elf_finish_dynamic_sections, but we
3346 must add the entries now so that we get the correct size for
3347 the .dynamic section. The DT_DEBUG entry is filled in by the
3348 dynamic linker and used by the debugger. */
1c0d3aa6
NC
3349
3350 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_DEBUG, 0))
0a1b45a2 3351 return false;
1c0d3aa6
NC
3352
3353 if (reltext)
07d6d2b8 3354 info->flags |= DF_TEXTREL;
1c0d3aa6
NC
3355
3356 if ((info->flags & DF_TEXTREL) != 0)
07d6d2b8
AM
3357 {
3358 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_TEXTREL, 0))
0a1b45a2 3359 return false;
07d6d2b8 3360 }
1c0d3aa6
NC
3361
3362 if (! SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0))
0a1b45a2 3363 return false;
1c0d3aa6 3364
0a1b45a2 3365 if (score_elf_rel_dyn_section (dynobj, false))
07d6d2b8
AM
3366 {
3367 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0))
0a1b45a2 3368 return false;
1c0d3aa6 3369
07d6d2b8 3370 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELSZ, 0))
0a1b45a2 3371 return false;
1c0d3aa6 3372
07d6d2b8 3373 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELENT, 0))
0a1b45a2 3374 return false;
07d6d2b8 3375 }
1c0d3aa6
NC
3376
3377 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_BASE_ADDRESS, 0))
0a1b45a2 3378 return false;
1c0d3aa6
NC
3379
3380 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_LOCAL_GOTNO, 0))
0a1b45a2 3381 return false;
1c0d3aa6
NC
3382
3383 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_SYMTABNO, 0))
0a1b45a2 3384 return false;
1c0d3aa6
NC
3385
3386 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_UNREFEXTNO, 0))
0a1b45a2 3387 return false;
1c0d3aa6
NC
3388
3389 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_GOTSYM, 0))
0a1b45a2 3390 return false;
1c0d3aa6
NC
3391
3392 if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_HIPAGENO, 0))
0a1b45a2 3393 return false;
1c0d3aa6
NC
3394 }
3395
0a1b45a2 3396 return true;
1c0d3aa6
NC
3397}
3398
0a1b45a2 3399static bool
c3b7224a 3400s3_bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
1c0d3aa6
NC
3401{
3402 struct elf_link_hash_entry *h;
3403 struct bfd_link_hash_entry *bh;
3404 flagword flags;
3405 asection *s;
3406
3407 flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
07d6d2b8 3408 | SEC_LINKER_CREATED | SEC_READONLY);
1c0d3aa6
NC
3409
3410 /* ABI requests the .dynamic section to be read only. */
3d4d4302 3411 s = bfd_get_linker_section (abfd, ".dynamic");
1c0d3aa6
NC
3412 if (s != NULL)
3413 {
fd361982 3414 if (!bfd_set_section_flags (s, flags))
0a1b45a2 3415 return false;
1c0d3aa6
NC
3416 }
3417
3418 /* We need to create .got section. */
0a1b45a2
AM
3419 if (!score_elf_create_got_section (abfd, info, false))
3420 return false;
1c0d3aa6 3421
0a1b45a2
AM
3422 if (!score_elf_rel_dyn_section (elf_hash_table (info)->dynobj, true))
3423 return false;
1c0d3aa6
NC
3424
3425 /* Create .stub section. */
3d4d4302 3426 if (bfd_get_linker_section (abfd, SCORE_ELF_STUB_SECTION_NAME) == NULL)
1c0d3aa6 3427 {
3d4d4302
AM
3428 s = bfd_make_section_anyway_with_flags (abfd, SCORE_ELF_STUB_SECTION_NAME,
3429 flags | SEC_CODE);
1c0d3aa6 3430 if (s == NULL
fd361982 3431 || !bfd_set_section_alignment (s, 2))
1c0d3aa6 3432
0a1b45a2 3433 return false;
1c0d3aa6
NC
3434 }
3435
0e1862bb 3436 if (!bfd_link_pic (info))
1c0d3aa6
NC
3437 {
3438 const char *name;
3439
3440 name = "_DYNAMIC_LINK";
3441 bh = NULL;
3442 if (!(_bfd_generic_link_add_one_symbol
07d6d2b8 3443 (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr,
0a1b45a2
AM
3444 (bfd_vma) 0, NULL, false, get_elf_backend_data (abfd)->collect, &bh)))
3445 return false;
1c0d3aa6
NC
3446
3447 h = (struct elf_link_hash_entry *)bh;
3448 h->non_elf = 0;
3449 h->def_regular = 1;
3450 h->type = STT_SECTION;
3451
3452 if (!bfd_elf_link_record_dynamic_symbol (info, h))
0a1b45a2 3453 return false;
1c0d3aa6
NC
3454 }
3455
0a1b45a2 3456 return true;
1c0d3aa6
NC
3457}
3458
3459
3460/* Finish up dynamic symbol handling. We set the contents of various
3461 dynamic sections here. */
0a1b45a2 3462static bool
c3b7224a 3463s3_bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd,
07d6d2b8
AM
3464 struct bfd_link_info *info,
3465 struct elf_link_hash_entry *h,
3466 Elf_Internal_Sym *sym)
1c0d3aa6
NC
3467{
3468 bfd *dynobj;
3469 asection *sgot;
3470 struct score_got_info *g;
3471 const char *name;
3472
3473 dynobj = elf_hash_table (info)->dynobj;
3474
3475 if (h->plt.offset != MINUS_ONE)
3476 {
3477 asection *s;
3478 bfd_byte stub[SCORE_FUNCTION_STUB_SIZE];
3479
3480 /* This symbol has a stub. Set it up. */
3481 BFD_ASSERT (h->dynindx != -1);
3482
3d4d4302 3483 s = bfd_get_linker_section (dynobj, SCORE_ELF_STUB_SECTION_NAME);
1c0d3aa6
NC
3484 BFD_ASSERT (s != NULL);
3485
3486 /* FIXME: Can h->dynindex be more than 64K? */
3487 if (h->dynindx & 0xffff0000)
0a1b45a2 3488 return false;
1c0d3aa6
NC
3489
3490 /* Fill the stub. */
c3b7224a
NC
3491 score_bfd_put_32 (output_bfd, STUB_LW, stub);
3492 score_bfd_put_32 (output_bfd, STUB_MOVE, stub + 4);
3493 score_bfd_put_32 (output_bfd, STUB_LI16 | (h->dynindx << 1), stub + 8);
3494 score_bfd_put_32 (output_bfd, STUB_BRL, stub + 12);
1c0d3aa6
NC
3495
3496 BFD_ASSERT (h->plt.offset <= s->size);
3497 memcpy (s->contents + h->plt.offset, stub, SCORE_FUNCTION_STUB_SIZE);
3498
3499 /* Mark the symbol as undefined. plt.offset != -1 occurs
07d6d2b8 3500 only for the referenced symbol. */
1c0d3aa6
NC
3501 sym->st_shndx = SHN_UNDEF;
3502
3503 /* The run-time linker uses the st_value field of the symbol
07d6d2b8
AM
3504 to reset the global offset table entry for this external
3505 to its stub address when unlinking a shared object. */
1c0d3aa6
NC
3506 sym->st_value = (s->output_section->vma + s->output_offset + h->plt.offset);
3507 }
3508
3509 BFD_ASSERT (h->dynindx != -1 || h->forced_local);
3510
0a1b45a2 3511 sgot = score_elf_got_section (dynobj, false);
1c0d3aa6
NC
3512 BFD_ASSERT (sgot != NULL);
3513 BFD_ASSERT (score_elf_section_data (sgot) != NULL);
3514 g = score_elf_section_data (sgot)->u.got_info;
3515 BFD_ASSERT (g != NULL);
3516
3517 /* Run through the global symbol table, creating GOT entries for all
3518 the symbols that need them. */
3519 if (g->global_gotsym != NULL && h->dynindx >= g->global_gotsym->dynindx)
3520 {
3521 bfd_vma offset;
3522 bfd_vma value;
3523
3524 value = sym->st_value;
3525 offset = score_elf_global_got_index (dynobj, h);
c3b7224a 3526 score_bfd_put_32 (output_bfd, value, sgot->contents + offset);
1c0d3aa6
NC
3527 }
3528
3529 /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
3530 name = h->root.root.string;
9637f6ef
L
3531 if (h == elf_hash_table (info)->hdynamic
3532 || h == elf_hash_table (info)->hgot)
1c0d3aa6
NC
3533 sym->st_shndx = SHN_ABS;
3534 else if (strcmp (name, "_DYNAMIC_LINK") == 0)
3535 {
3536 sym->st_shndx = SHN_ABS;
3537 sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
3538 sym->st_value = 1;
3539 }
3540 else if (strcmp (name, GP_DISP_LABEL) == 0)
3541 {
3542 sym->st_shndx = SHN_ABS;
3543 sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
3544 sym->st_value = elf_gp (output_bfd);
3545 }
3546
0a1b45a2 3547 return true;
1c0d3aa6
NC
3548}
3549
3550/* Finish up the dynamic sections. */
0a1b45a2 3551static bool
c3b7224a 3552s3_bfd_score_elf_finish_dynamic_sections (bfd *output_bfd,
07d6d2b8 3553 struct bfd_link_info *info)
1c0d3aa6
NC
3554{
3555 bfd *dynobj;
3556 asection *sdyn;
3557 asection *sgot;
3558 asection *s;
3559 struct score_got_info *g;
3560
3561 dynobj = elf_hash_table (info)->dynobj;
3562
3d4d4302 3563 sdyn = bfd_get_linker_section (dynobj, ".dynamic");
1c0d3aa6 3564
0a1b45a2 3565 sgot = score_elf_got_section (dynobj, false);
1c0d3aa6
NC
3566 if (sgot == NULL)
3567 g = NULL;
3568 else
3569 {
3570 BFD_ASSERT (score_elf_section_data (sgot) != NULL);
3571 g = score_elf_section_data (sgot)->u.got_info;
3572 BFD_ASSERT (g != NULL);
3573 }
3574
3575 if (elf_hash_table (info)->dynamic_sections_created)
3576 {
3577 bfd_byte *b;
3578
3579 BFD_ASSERT (sdyn != NULL);
3580 BFD_ASSERT (g != NULL);
3581
3582 for (b = sdyn->contents;
07d6d2b8
AM
3583 b < sdyn->contents + sdyn->size;
3584 b += SCORE_ELF_DYN_SIZE (dynobj))
3585 {
3586 Elf_Internal_Dyn dyn;
3587 const char *name;
3588 size_t elemsize;
0a1b45a2 3589 bool swap_out_p;
07d6d2b8
AM
3590
3591 /* Read in the current dynamic entry. */
3592 (*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn);
3593
3594 /* Assume that we're going to modify it and write it out. */
0a1b45a2 3595 swap_out_p = true;
07d6d2b8
AM
3596
3597 switch (dyn.d_tag)
3598 {
3599 case DT_RELENT:
3600 dyn.d_un.d_val = SCORE_ELF_REL_SIZE (dynobj);
3601 break;
3602
3603 case DT_STRSZ:
3604 /* Rewrite DT_STRSZ. */
3605 dyn.d_un.d_val
3606 = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
3607 break;
3608
3609 case DT_PLTGOT:
3610 s = elf_hash_table (info)->sgot;
3611 dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
3612 break;
3613
3614 case DT_SCORE_BASE_ADDRESS:
3615 s = output_bfd->sections;
3616 BFD_ASSERT (s != NULL);
3617 dyn.d_un.d_ptr = s->vma & ~(bfd_vma) 0xffff;
3618 break;
3619
3620 case DT_SCORE_LOCAL_GOTNO:
3621 dyn.d_un.d_val = g->local_gotno;
3622 break;
3623
3624 case DT_SCORE_UNREFEXTNO:
3625 /* The index into the dynamic symbol table which is the
3626 entry of the first external symbol that is not
3627 referenced within the same object. */
3628 dyn.d_un.d_val = bfd_count_sections (output_bfd) + 1;
3629 break;
3630
3631 case DT_SCORE_GOTSYM:
3632 if (g->global_gotsym)
3633 {
3634 dyn.d_un.d_val = g->global_gotsym->dynindx;
3635 break;
3636 }
3637 /* In case if we don't have global got symbols we default
3638 to setting DT_SCORE_GOTSYM to the same value as
3639 DT_SCORE_SYMTABNO. */
1a0670f3 3640 /* Fall through. */
c3b7224a 3641
07d6d2b8
AM
3642 case DT_SCORE_SYMTABNO:
3643 name = ".dynsym";
3644 elemsize = SCORE_ELF_SYM_SIZE (output_bfd);
3645 s = bfd_get_linker_section (dynobj, name);
3646 dyn.d_un.d_val = s->size / elemsize;
3647 break;
3648
3649 case DT_SCORE_HIPAGENO:
3650 dyn.d_un.d_val = g->local_gotno - SCORE_RESERVED_GOTNO;
3651 break;
3652
3653 default:
0a1b45a2 3654 swap_out_p = false;
07d6d2b8
AM
3655 break;
3656 }
3657
3658 if (swap_out_p)
3659 (*get_elf_backend_data (dynobj)->s->swap_dyn_out) (dynobj, &dyn, b);
3660 }
1c0d3aa6
NC
3661 }
3662
3663 /* The first entry of the global offset table will be filled at
3664 runtime. The second entry will be used by some runtime loaders.
3665 This isn't the case of IRIX rld. */
3666 if (sgot != NULL && sgot->size > 0)
3667 {
c3b7224a
NC
3668 score_bfd_put_32 (output_bfd, 0, sgot->contents);
3669 score_bfd_put_32 (output_bfd, 0x80000000, sgot->contents + SCORE_ELF_GOT_SIZE (output_bfd));
1c0d3aa6
NC
3670 }
3671
3672 if (sgot != NULL)
3673 elf_section_data (sgot->output_section)->this_hdr.sh_entsize
3674 = SCORE_ELF_GOT_SIZE (output_bfd);
3675
3676
3677 /* We need to sort the entries of the dynamic relocation section. */
0a1b45a2 3678 s = score_elf_rel_dyn_section (dynobj, false);
1c0d3aa6
NC
3679
3680 if (s != NULL && s->size > (bfd_vma)2 * SCORE_ELF_REL_SIZE (output_bfd))
3681 {
3682 reldyn_sorting_bfd = output_bfd;
3683 qsort ((Elf32_External_Rel *) s->contents + 1, s->reloc_count - 1,
07d6d2b8 3684 sizeof (Elf32_External_Rel), score_elf_sort_dynamic_relocs);
1c0d3aa6
NC
3685 }
3686
0a1b45a2 3687 return true;
1c0d3aa6
NC
3688}
3689
3690/* This function set up the ELF section header for a BFD section in preparation for writing
3691 it out. This is where the flags and type fields are set for unusual sections. */
0a1b45a2 3692static bool
c3b7224a 3693s3_bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
07d6d2b8
AM
3694 Elf_Internal_Shdr *hdr,
3695 asection *sec)
1c0d3aa6
NC
3696{
3697 const char *name;
3698
fd361982 3699 name = bfd_section_name (sec);
1c0d3aa6
NC
3700
3701 if (strcmp (name, ".got") == 0
3702 || strcmp (name, ".srdata") == 0
3703 || strcmp (name, ".sdata") == 0
3704 || strcmp (name, ".sbss") == 0)
3705 hdr->sh_flags |= SHF_SCORE_GPREL;
3706
0a1b45a2 3707 return true;
1c0d3aa6
NC
3708}
3709
3710/* This function do additional processing on the ELF section header before writing
3711 it out. This is used to set the flags and type fields for some sections. */
3712
3713/* assign_file_positions_except_relocs() check section flag and if it is allocatable,
3714 warning message will be issued. backend_fake_section is called before
3715 assign_file_positions_except_relocs(); backend_section_processing after it. so, we
3716 modify section flag there, but not backend_fake_section. */
0a1b45a2 3717static bool
c3b7224a 3718s3_bfd_score_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr)
1c0d3aa6
NC
3719{
3720 if (hdr->bfd_section != NULL)
3721 {
fd361982 3722 const char *name = bfd_section_name (hdr->bfd_section);
1c0d3aa6
NC
3723
3724 if (strcmp (name, ".sdata") == 0)
07d6d2b8
AM
3725 {
3726 hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_SCORE_GPREL;
3727 hdr->sh_type = SHT_PROGBITS;
3728 }
1c0d3aa6 3729 else if (strcmp (name, ".sbss") == 0)
07d6d2b8
AM
3730 {
3731 hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_SCORE_GPREL;
3732 hdr->sh_type = SHT_NOBITS;
3733 }
1c0d3aa6 3734 else if (strcmp (name, ".srdata") == 0)
07d6d2b8
AM
3735 {
3736 hdr->sh_flags |= SHF_ALLOC | SHF_SCORE_GPREL;
3737 hdr->sh_type = SHT_PROGBITS;
3738 }
1c0d3aa6
NC
3739 }
3740
0a1b45a2 3741 return true;
1c0d3aa6
NC
3742}
3743
0a1b45a2 3744static bool
c3b7224a 3745s3_bfd_score_elf_write_section (bfd *output_bfd, asection *sec, bfd_byte *contents)
1c0d3aa6
NC
3746{
3747 bfd_byte *to, *from, *end;
3748 int i;
3749
3750 if (strcmp (sec->name, ".pdr") != 0)
0a1b45a2 3751 return false;
1c0d3aa6
NC
3752
3753 if (score_elf_section_data (sec)->u.tdata == NULL)
0a1b45a2 3754 return false;
1c0d3aa6
NC
3755
3756 to = contents;
3757 end = contents + sec->size;
3758 for (from = contents, i = 0; from < end; from += PDR_SIZE, i++)
3759 {
3760 if ((score_elf_section_data (sec)->u.tdata)[i] == 1)
07d6d2b8 3761 continue;
1c0d3aa6
NC
3762
3763 if (to != from)
07d6d2b8 3764 memcpy (to, from, PDR_SIZE);
1c0d3aa6
NC
3765
3766 to += PDR_SIZE;
3767 }
3768 bfd_set_section_contents (output_bfd, sec->output_section, contents,
07d6d2b8 3769 (file_ptr) sec->output_offset, sec->size);
1c0d3aa6 3770
0a1b45a2 3771 return true;
1c0d3aa6
NC
3772}
3773
3774/* Copy data from a SCORE ELF indirect symbol to its direct symbol, hiding the old
3775 indirect symbol. Process additional relocation information. */
1c0d3aa6 3776static void
c3b7224a 3777s3_bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info,
07d6d2b8
AM
3778 struct elf_link_hash_entry *dir,
3779 struct elf_link_hash_entry *ind)
1c0d3aa6
NC
3780{
3781 struct score_elf_link_hash_entry *dirscore, *indscore;
3782
3783 _bfd_elf_link_hash_copy_indirect (info, dir, ind);
3784
3785 if (ind->root.type != bfd_link_hash_indirect)
3786 return;
3787
3788 dirscore = (struct score_elf_link_hash_entry *) dir;
3789 indscore = (struct score_elf_link_hash_entry *) ind;
3790 dirscore->possibly_dynamic_relocs += indscore->possibly_dynamic_relocs;
3791
3792 if (indscore->readonly_reloc)
0a1b45a2 3793 dirscore->readonly_reloc = true;
1c0d3aa6
NC
3794
3795 if (indscore->no_fn_stub)
0a1b45a2 3796 dirscore->no_fn_stub = true;
1c0d3aa6
NC
3797}
3798
3799/* Remove information about discarded functions from other sections which mention them. */
0a1b45a2 3800static bool
c3b7224a 3801s3_bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie,
07d6d2b8 3802 struct bfd_link_info *info)
1c0d3aa6
NC
3803{
3804 asection *o;
0a1b45a2 3805 bool ret = false;
1c0d3aa6
NC
3806 unsigned char *tdata;
3807 size_t i, skip;
3808
3809 o = bfd_get_section_by_name (abfd, ".pdr");
3810 if ((!o) || (o->size == 0) || (o->size % PDR_SIZE != 0)
3811 || (o->output_section != NULL && bfd_is_abs_section (o->output_section)))
0a1b45a2 3812 return false;
1c0d3aa6
NC
3813
3814 tdata = bfd_zmalloc (o->size / PDR_SIZE);
3815 if (!tdata)
0a1b45a2 3816 return false;
1c0d3aa6
NC
3817
3818 cookie->rels = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, info->keep_memory);
3819 if (!cookie->rels)
3820 {
3821 free (tdata);
0a1b45a2 3822 return false;
1c0d3aa6
NC
3823 }
3824
3825 cookie->rel = cookie->rels;
3826 cookie->relend = cookie->rels + o->reloc_count;
3827
3828 for (i = 0, skip = 0; i < o->size; i++)
3829 {
3830 if (bfd_elf_reloc_symbol_deleted_p (i * PDR_SIZE, cookie))
07d6d2b8
AM
3831 {
3832 tdata[i] = 1;
3833 skip++;
3834 }
1c0d3aa6
NC
3835 }
3836
3837 if (skip != 0)
3838 {
3839 score_elf_section_data (o)->u.tdata = tdata;
3840 o->size -= skip * PDR_SIZE;
0a1b45a2 3841 ret = true;
1c0d3aa6
NC
3842 }
3843 else
3844 free (tdata);
3845
3846 if (!info->keep_memory)
3847 free (cookie->rels);
3848
3849 return ret;
3850}
3851
3852/* Signal that discard_info() has removed the discarded relocations for this section. */
0a1b45a2 3853static bool
c3b7224a 3854s3_bfd_score_elf_ignore_discarded_relocs (asection *sec)
1c0d3aa6
NC
3855{
3856 if (strcmp (sec->name, ".pdr") == 0)
0a1b45a2
AM
3857 return true;
3858 return false;
1c0d3aa6
NC
3859}
3860
07adf181
AM
3861/* Return the section that should be marked against GC for a given
3862 relocation. */
1c0d3aa6 3863static asection *
c3b7224a 3864s3_bfd_score_elf_gc_mark_hook (asection *sec,
07d6d2b8
AM
3865 struct bfd_link_info *info,
3866 Elf_Internal_Rela *rel,
3867 struct elf_link_hash_entry *h,
3868 Elf_Internal_Sym *sym)
1c0d3aa6
NC
3869{
3870 if (h != NULL)
07adf181
AM
3871 switch (ELF32_R_TYPE (rel->r_info))
3872 {
3873 case R_SCORE_GNU_VTINHERIT:
3874 case R_SCORE_GNU_VTENTRY:
07d6d2b8 3875 return NULL;
07adf181 3876 }
1c0d3aa6 3877
07adf181 3878 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
1c0d3aa6
NC
3879}
3880
3881/* Support for core dump NOTE sections. */
3882
0a1b45a2 3883static bool
c3b7224a 3884s3_bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
1c0d3aa6
NC
3885{
3886 int offset;
3887 unsigned int raw_size;
3888
3889 switch (note->descsz)
3890 {
3891 default:
0a1b45a2 3892 return false;
1c0d3aa6 3893
07d6d2b8 3894 case 148: /* Linux/Score 32-bit. */
1c0d3aa6 3895 /* pr_cursig */
228e534f
AM
3896 elf_tdata (abfd)->core->signal
3897 = score_bfd_get_16 (abfd, note->descdata + 12);
1c0d3aa6
NC
3898
3899 /* pr_pid */
228e534f
AM
3900 elf_tdata (abfd)->core->lwpid
3901 = score_bfd_get_32 (abfd, note->descdata + 24);
1c0d3aa6
NC
3902
3903 /* pr_reg */
3904 offset = 72;
3905 raw_size = 72;
3906
3907 break;
3908 }
3909
3910 /* Make a ".reg/999" section. */
228e534f
AM
3911 return _bfd_elfcore_make_pseudosection (abfd, ".reg", raw_size,
3912 note->descpos + offset);
1c0d3aa6
NC
3913}
3914
0a1b45a2 3915static bool
c3b7224a 3916s3_bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
1c0d3aa6
NC
3917{
3918 switch (note->descsz)
3919 {
3920 default:
0a1b45a2 3921 return false;
1c0d3aa6 3922
07d6d2b8 3923 case 124: /* Linux/Score elf_prpsinfo. */
228e534f
AM
3924 elf_tdata (abfd)->core->program
3925 = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16);
3926 elf_tdata (abfd)->core->command
3927 = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80);
1c0d3aa6
NC
3928 }
3929
3930 /* Note that for some reason, a spurious space is tacked
3931 onto the end of the args in some (at least one anyway)
3932 implementations, so strip it off if it exists. */
3933
3934 {
228e534f 3935 char *command = elf_tdata (abfd)->core->command;
1c0d3aa6
NC
3936 int n = strlen (command);
3937
3938 if (0 < n && command[n - 1] == ' ')
3939 command[n - 1] = '\0';
3940 }
3941
0a1b45a2 3942 return true;
1c0d3aa6
NC
3943}
3944
3945
3946/* Score BFD functions. */
1c0d3aa6 3947static reloc_howto_type *
c3b7224a 3948s3_elf32_score_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
1c0d3aa6
NC
3949{
3950 unsigned int i;
3951
c3b7224a 3952 for (i = 0; i < ARRAY_SIZE (elf32_score_reloc_map); i++)
1c0d3aa6
NC
3953 if (elf32_score_reloc_map[i].bfd_reloc_val == code)
3954 return &elf32_score_howto_table[elf32_score_reloc_map[i].elf_reloc_val];
3955
3956 return NULL;
3957}
3958
157090f7
AM
3959static reloc_howto_type *
3960elf32_score_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
07d6d2b8 3961 const char *r_name)
157090f7
AM
3962{
3963 unsigned int i;
3964
3965 for (i = 0;
3966 i < (sizeof (elf32_score_howto_table)
07d6d2b8 3967 / sizeof (elf32_score_howto_table[0]));
157090f7
AM
3968 i++)
3969 if (elf32_score_howto_table[i].name != NULL
07d6d2b8 3970 && strcasecmp (elf32_score_howto_table[i].name, r_name) == 0)
157090f7
AM
3971 return &elf32_score_howto_table[i];
3972
3973 return NULL;
3974}
3975
0a1b45a2 3976static bool
c3b7224a 3977s3_elf32_score_print_private_bfd_data (bfd *abfd, void * ptr)
1c0d3aa6
NC
3978{
3979 FILE *file = (FILE *) ptr;
3980
3981 BFD_ASSERT (abfd != NULL && ptr != NULL);
3982
3983 /* Print normal ELF private data. */
3984 _bfd_elf_print_private_bfd_data (abfd, ptr);
3985
3986 /* xgettext:c-format */
3987 fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
3988 if (elf_elfheader (abfd)->e_flags & EF_SCORE_PIC)
3989 {
3990 fprintf (file, _(" [pic]"));
3991 }
3992 if (elf_elfheader (abfd)->e_flags & EF_SCORE_FIXDEP)
3993 {
3994 fprintf (file, _(" [fix dep]"));
3995 }
3996 fputc ('\n', file);
3997
0a1b45a2 3998 return true;
1c0d3aa6
NC
3999}
4000
0a1b45a2 4001static bool
50e03d47 4002s3_elf32_score_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
1c0d3aa6 4003{
50e03d47 4004 bfd *obfd = info->output_bfd;
1c0d3aa6
NC
4005 flagword in_flags;
4006 flagword out_flags;
4007
50e03d47 4008 if (!_bfd_generic_verify_endian_match (ibfd, info))
0a1b45a2 4009 return false;
1c0d3aa6 4010
6b728d32
AM
4011 /* FIXME: What should be checked when linking shared libraries? */
4012 if ((ibfd->flags & DYNAMIC) != 0)
0a1b45a2 4013 return true;
6b728d32 4014
1c0d3aa6
NC
4015 in_flags = elf_elfheader (ibfd)->e_flags;
4016 out_flags = elf_elfheader (obfd)->e_flags;
4017
4018 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
4019 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
0a1b45a2 4020 return true;
1c0d3aa6
NC
4021
4022 in_flags = elf_elfheader (ibfd)->e_flags;
4023 out_flags = elf_elfheader (obfd)->e_flags;
4024
4025 if (! elf_flags_init (obfd))
4026 {
0a1b45a2 4027 elf_flags_init (obfd) = true;
1c0d3aa6
NC
4028 elf_elfheader (obfd)->e_flags = in_flags;
4029
4030 if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
07d6d2b8
AM
4031 && bfd_get_arch_info (obfd)->the_default)
4032 {
4033 return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
4034 }
1c0d3aa6 4035
0a1b45a2 4036 return true;
1c0d3aa6
NC
4037 }
4038
4039 if (((in_flags & EF_SCORE_PIC) != 0) != ((out_flags & EF_SCORE_PIC) != 0))
4eca0228 4040 _bfd_error_handler
871b3ab2 4041 (_("%pB: warning: linking PIC files with non-PIC files"), ibfd);
1c0d3aa6
NC
4042
4043 /* FIXME: Maybe dependency fix compatibility should be checked here. */
4044
0a1b45a2 4045 return true;
1c0d3aa6
NC
4046}
4047
0a1b45a2 4048static bool
c3b7224a 4049s3_elf32_score_new_section_hook (bfd *abfd, asection *sec)
1c0d3aa6
NC
4050{
4051 struct _score_elf_section_data *sdata;
986f0783 4052 size_t amt = sizeof (*sdata);
1c0d3aa6
NC
4053
4054 sdata = bfd_zalloc (abfd, amt);
4055 if (sdata == NULL)
0a1b45a2 4056 return false;
1c0d3aa6
NC
4057 sec->used_by_bfd = sdata;
4058
4059 return _bfd_elf_new_section_hook (abfd, sec);
4060}
4061
c3b7224a
NC
4062/*****************************************************************************/
4063
4064/* s3_s7: backend hooks. */
0a1b45a2 4065static bool
c3b7224a 4066_bfd_score_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
07d6d2b8
AM
4067 arelent *bfd_reloc,
4068 Elf_Internal_Rela *elf_reloc)
c3b7224a
NC
4069{
4070 if (bfd_get_mach (abfd) == bfd_mach_score3)
4071 return s3_bfd_score_info_to_howto (abfd, bfd_reloc, elf_reloc);
4072 else
4073 return s7_bfd_score_info_to_howto (abfd, bfd_reloc, elf_reloc);
4074}
4075
0f684201 4076static int
c3b7224a 4077_bfd_score_elf_relocate_section (bfd *output_bfd,
07d6d2b8
AM
4078 struct bfd_link_info *info,
4079 bfd *input_bfd,
4080 asection *input_section,
4081 bfd_byte *contents,
4082 Elf_Internal_Rela *relocs,
4083 Elf_Internal_Sym *local_syms,
4084 asection **local_sections)
c3b7224a
NC
4085{
4086 if (bfd_get_mach (output_bfd) == bfd_mach_score3)
4087 return s3_bfd_score_elf_relocate_section (output_bfd,
07d6d2b8
AM
4088 info, input_bfd, input_section, contents, relocs,
4089 local_syms, local_sections);
c3b7224a
NC
4090 else
4091 return s7_bfd_score_elf_relocate_section (output_bfd,
07d6d2b8
AM
4092 info, input_bfd, input_section, contents, relocs,
4093 local_syms, local_sections);
c3b7224a
NC
4094}
4095
0a1b45a2 4096static bool
c3b7224a 4097_bfd_score_elf_check_relocs (bfd *abfd,
07d6d2b8
AM
4098 struct bfd_link_info *info,
4099 asection *sec,
4100 const Elf_Internal_Rela *relocs)
c3b7224a
NC
4101{
4102 if (bfd_get_mach (abfd) == bfd_mach_score3)
4103 return s3_bfd_score_elf_check_relocs (abfd, info, sec, relocs);
4104 else
4105 return s7_bfd_score_elf_check_relocs (abfd, info, sec, relocs);
4106}
4107
0a1b45a2 4108static bool
c3b7224a 4109_bfd_score_elf_add_symbol_hook (bfd *abfd,
07d6d2b8
AM
4110 struct bfd_link_info *info ATTRIBUTE_UNUSED,
4111 Elf_Internal_Sym *sym,
4112 const char **namep ATTRIBUTE_UNUSED,
4113 flagword *flagsp ATTRIBUTE_UNUSED,
4114 asection **secp,
4115 bfd_vma *valp)
c3b7224a
NC
4116{
4117 if (bfd_get_mach (abfd) == bfd_mach_score3)
4118 return s3_bfd_score_elf_add_symbol_hook (abfd, info, sym, namep, flagsp,
07d6d2b8 4119 secp, valp);
c3b7224a
NC
4120 else
4121 return s7_bfd_score_elf_add_symbol_hook (abfd, info, sym, namep, flagsp,
07d6d2b8 4122 secp, valp);
c3b7224a
NC
4123}
4124
4125static void
4126_bfd_score_elf_symbol_processing (bfd *abfd, asymbol *asym)
4127{
4128 if (bfd_get_mach (abfd) == bfd_mach_score3)
4129 return s3_bfd_score_elf_symbol_processing (abfd, asym);
4130 else
4131 return s7_bfd_score_elf_symbol_processing (abfd, asym);
4132}
4133
6e0b88f1 4134static int
c3b7224a
NC
4135_bfd_score_elf_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED,
4136 const char *name ATTRIBUTE_UNUSED,
4137 Elf_Internal_Sym *sym,
4138 asection *input_sec,
4139 struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
4140{
4141 /* If link a empty .o, then this filed is NULL. */
4142 if (info->input_bfds == NULL)
4143 {
4144 /* If we see a common symbol, which implies a relocatable link, then
07d6d2b8
AM
4145 if a symbol was small common in an input file, mark it as small
4146 common in the output file. */
c3b7224a 4147 if (sym->st_shndx == SHN_COMMON && strcmp (input_sec->name, ".scommon") == 0)
07d6d2b8 4148 sym->st_shndx = SHN_SCORE_SCOMMON;
6e0b88f1 4149 return 1;
c3b7224a
NC
4150 }
4151
4152 if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
4153 return s3_bfd_score_elf_link_output_symbol_hook (info, name, sym, input_sec, h);
4154 else
4155 return s7_bfd_score_elf_link_output_symbol_hook (info, name, sym, input_sec, h);
4156}
4157
0a1b45a2 4158static bool
c3b7224a 4159_bfd_score_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
07d6d2b8
AM
4160 asection *sec,
4161 int *retval)
c3b7224a
NC
4162{
4163 if (bfd_get_mach (abfd) == bfd_mach_score3)
4164 return s3_bfd_score_elf_section_from_bfd_section (abfd, sec, retval);
4165 else
4166 return s7_bfd_score_elf_section_from_bfd_section (abfd, sec, retval);
4167}
4168
0a1b45a2 4169static bool
c3b7224a 4170_bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
07d6d2b8 4171 struct elf_link_hash_entry *h)
c3b7224a
NC
4172{
4173 if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
4174 return s3_bfd_score_elf_adjust_dynamic_symbol (info, h);
4175 else
4176 return s7_bfd_score_elf_adjust_dynamic_symbol (info, h);
4177}
4178
0a1b45a2 4179static bool
c3b7224a 4180_bfd_score_elf_always_size_sections (bfd *output_bfd,
07d6d2b8 4181 struct bfd_link_info *info)
c3b7224a
NC
4182{
4183 if (bfd_get_mach (output_bfd) == bfd_mach_score3)
4184 return s3_bfd_score_elf_always_size_sections (output_bfd, info);
4185 else
4186 return s7_bfd_score_elf_always_size_sections (output_bfd, info);
4187}
4188
0a1b45a2 4189static bool
c3b7224a
NC
4190_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
4191{
4192 if (bfd_get_mach (output_bfd) == bfd_mach_score3)
4193 return s3_bfd_score_elf_size_dynamic_sections (output_bfd, info);
4194 else
4195 return s7_bfd_score_elf_size_dynamic_sections (output_bfd, info);
4196}
4197
0a1b45a2 4198static bool
c3b7224a
NC
4199_bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
4200{
4201 if (bfd_get_mach (abfd) == bfd_mach_score3)
4202 return s3_bfd_score_elf_create_dynamic_sections (abfd, info);
4203 else
4204 return s7_bfd_score_elf_create_dynamic_sections (abfd, info);
4205}
4206
0a1b45a2 4207static bool
c3b7224a 4208_bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd,
07d6d2b8
AM
4209 struct bfd_link_info *info,
4210 struct elf_link_hash_entry *h,
4211 Elf_Internal_Sym *sym)
c3b7224a
NC
4212{
4213 if (bfd_get_mach (output_bfd) == bfd_mach_score3)
4214 return s3_bfd_score_elf_finish_dynamic_symbol (output_bfd, info, h, sym);
4215 else
4216 return s7_bfd_score_elf_finish_dynamic_symbol (output_bfd, info, h, sym);
4217}
4218
0a1b45a2 4219static bool
c3b7224a 4220_bfd_score_elf_finish_dynamic_sections (bfd *output_bfd,
07d6d2b8 4221 struct bfd_link_info *info)
c3b7224a
NC
4222{
4223 if (bfd_get_mach (output_bfd) == bfd_mach_score3)
4224 return s3_bfd_score_elf_finish_dynamic_sections (output_bfd, info);
4225 else
4226 return s7_bfd_score_elf_finish_dynamic_sections (output_bfd, info);
4227}
4228
0a1b45a2 4229static bool
c3b7224a 4230_bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
07d6d2b8
AM
4231 Elf_Internal_Shdr *hdr,
4232 asection *sec)
c3b7224a
NC
4233{
4234 if (bfd_get_mach (abfd) == bfd_mach_score3)
4235 return s3_bfd_score_elf_fake_sections (abfd, hdr, sec);
4236 else
4237 return s7_bfd_score_elf_fake_sections (abfd, hdr, sec);
4238}
4239
0a1b45a2 4240static bool
c3b7224a
NC
4241_bfd_score_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr)
4242{
4243 if (bfd_get_mach (abfd) == bfd_mach_score3)
4244 return s3_bfd_score_elf_section_processing (abfd, hdr);
4245 else
4246 return s7_bfd_score_elf_section_processing (abfd, hdr);
4247}
4248
0a1b45a2 4249static bool
c3b7224a 4250_bfd_score_elf_write_section (bfd *output_bfd,
07d6d2b8
AM
4251 struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
4252 asection *sec, bfd_byte *contents)
c3b7224a
NC
4253{
4254 if (bfd_get_mach (output_bfd) == bfd_mach_score3)
4255 return s3_bfd_score_elf_write_section (output_bfd, sec, contents);
4256 else
4257 return s7_bfd_score_elf_write_section (output_bfd, sec, contents);
4258}
4259
4260static void
4261_bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info,
07d6d2b8
AM
4262 struct elf_link_hash_entry *dir,
4263 struct elf_link_hash_entry *ind)
c3b7224a
NC
4264{
4265 if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
4266 return s3_bfd_score_elf_copy_indirect_symbol (info, dir, ind);
4267 else
4268 return s7_bfd_score_elf_copy_indirect_symbol (info, dir, ind);
4269}
4270
4271static void
4272_bfd_score_elf_hide_symbol (struct bfd_link_info *info,
07d6d2b8 4273 struct elf_link_hash_entry *entry,
0a1b45a2 4274 bool force_local)
c3b7224a
NC
4275{
4276 if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
4277 return s3_bfd_score_elf_hide_symbol (info, entry, force_local);
4278 else
4279 return s7_bfd_score_elf_hide_symbol (info, entry, force_local);
4280}
4281
0a1b45a2 4282static bool
c3b7224a 4283_bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie,
07d6d2b8 4284 struct bfd_link_info *info)
c3b7224a
NC
4285{
4286 if (bfd_get_mach (abfd) == bfd_mach_score3)
4287 return s3_bfd_score_elf_discard_info (abfd, cookie, info);
4288 else
4289 return s7_bfd_score_elf_discard_info (abfd, cookie, info);
4290}
4291
0a1b45a2 4292static bool
c3b7224a
NC
4293_bfd_score_elf_ignore_discarded_relocs (asection *sec)
4294{
4295 if (bfd_get_mach (sec->owner) == bfd_mach_score3)
4296 return s3_bfd_score_elf_ignore_discarded_relocs (sec);
4297 else
4298 return s7_bfd_score_elf_ignore_discarded_relocs (sec);
4299}
4300
4301static asection *
4302_bfd_score_elf_gc_mark_hook (asection *sec,
07d6d2b8
AM
4303 struct bfd_link_info *info,
4304 Elf_Internal_Rela *rel,
4305 struct elf_link_hash_entry *h,
4306 Elf_Internal_Sym *sym)
c3b7224a
NC
4307{
4308 if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
4309 return s3_bfd_score_elf_gc_mark_hook (sec, info, rel, h, sym);
4310 else
4311 return s7_bfd_score_elf_gc_mark_hook (sec, info, rel, h, sym);
4312}
4313
0a1b45a2 4314static bool
c3b7224a
NC
4315_bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
4316{
4317 if (bfd_get_mach (abfd) == bfd_mach_score3)
4318 return s3_bfd_score_elf_grok_prstatus (abfd, note);
4319 else
4320 return s7_bfd_score_elf_grok_prstatus (abfd, note);
4321}
4322
0a1b45a2 4323static bool
c3b7224a
NC
4324_bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
4325{
4326 if (bfd_get_mach (abfd) == bfd_mach_score3)
4327 return s3_bfd_score_elf_grok_psinfo (abfd, note);
4328 else
4329 return s7_bfd_score_elf_grok_psinfo (abfd, note);
4330}
4331
4332static reloc_howto_type *
4333elf32_score_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
4334{
4335 /* s3: NOTE!!!
4336 gas will call elf32_score_reloc_type_lookup, and don't write elf file.
4337 So just using score3, but we don't know ld will call this or not.
4338 If so, this way can't work. */
4339
4340 if (score3)
4341 return s3_elf32_score_reloc_type_lookup (abfd, code);
4342 else
4343 return s7_elf32_score_reloc_type_lookup (abfd, code);
4344}
4345
4dfe6ac6
NC
4346/* Create a score elf linker hash table.
4347 This is a copy of _bfd_elf_link_hash_table_create() except with a
4348 different hash table entry creation function. */
4349
c3b7224a
NC
4350static struct bfd_link_hash_table *
4351elf32_score_link_hash_table_create (bfd *abfd)
4352{
4dfe6ac6 4353 struct elf_link_hash_table *ret;
986f0783 4354 size_t amt = sizeof (struct elf_link_hash_table);
4dfe6ac6 4355
7bf52ea2 4356 ret = (struct elf_link_hash_table *) bfd_zmalloc (amt);
4dfe6ac6
NC
4357 if (ret == NULL)
4358 return NULL;
4359
4360 if (!_bfd_elf_link_hash_table_init (ret, abfd, score_elf_link_hash_newfunc,
07d6d2b8 4361 sizeof (struct score_elf_link_hash_entry),
4dfe6ac6
NC
4362 GENERIC_ELF_DATA))
4363 {
4364 free (ret);
4365 return NULL;
4366 }
4367
4368 return &ret->root;
c3b7224a
NC
4369}
4370
0a1b45a2 4371static bool
c3b7224a
NC
4372elf32_score_print_private_bfd_data (bfd *abfd, void * ptr)
4373{
4374 if (bfd_get_mach (abfd) == bfd_mach_score3)
4375 return s3_elf32_score_print_private_bfd_data (abfd, ptr);
4376 else
4377 return s7_elf32_score_print_private_bfd_data (abfd, ptr);
4378}
4379
0a1b45a2 4380static bool
50e03d47 4381elf32_score_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
c3b7224a 4382{
50e03d47
AM
4383 if (bfd_get_mach (info->output_bfd) == bfd_mach_score3)
4384 return s3_elf32_score_merge_private_bfd_data (ibfd, info);
c3b7224a 4385 else
50e03d47 4386 return s7_elf32_score_merge_private_bfd_data (ibfd, info);
c3b7224a
NC
4387}
4388
0a1b45a2 4389static bool
c3b7224a
NC
4390elf32_score_new_section_hook (bfd *abfd, asection *sec)
4391{
4392 if (bfd_get_mach (abfd) == bfd_mach_score3)
4393 return s3_elf32_score_new_section_hook (abfd, sec);
4394 else
4395 return s7_elf32_score_new_section_hook (abfd, sec);
4396}
4397
4398
4399/* s3_s7: don't need to split. */
4400
4401/* Set the right machine number. */
0a1b45a2 4402static bool
c3b7224a
NC
4403_bfd_score_elf_score_object_p (bfd * abfd)
4404{
4405 int e_set = bfd_mach_score7;
4406
4407 if (elf_elfheader (abfd)->e_machine == EM_SCORE)
4408 {
4409 int e_mach = elf_elfheader (abfd)->e_flags & EF_SCORE_MACH & EF_OMIT_PIC_FIXDD;
4410 switch (e_mach)
07d6d2b8
AM
4411 {
4412 /* Set default target is score7. */
4413 default:
4414 case E_SCORE_MACH_SCORE7:
4415 e_set = bfd_mach_score7;
4416 break;
4417
4418 case E_SCORE_MACH_SCORE3:
4419 e_set = bfd_mach_score3;
4420 break;
4421 }
c3b7224a
NC
4422 }
4423
4424 return bfd_default_set_arch_mach (abfd, bfd_arch_score, e_set);
4425}
4426
0a1b45a2 4427bool
c3b7224a
NC
4428_bfd_score_elf_common_definition (Elf_Internal_Sym *sym)
4429{
4430 return (sym->st_shndx == SHN_COMMON || sym->st_shndx == SHN_SCORE_SCOMMON);
4431}
4432
4433/*****************************************************************************/
4434
1c0d3aa6 4435
07d6d2b8
AM
4436#define USE_REL 1
4437#define TARGET_LITTLE_SYM score_elf32_le_vec
4438#define TARGET_LITTLE_NAME "elf32-littlescore"
4439#define TARGET_BIG_SYM score_elf32_be_vec
4440#define TARGET_BIG_NAME "elf32-bigscore"
4441#define ELF_ARCH bfd_arch_score
4442#define ELF_MACHINE_CODE EM_SCORE
4443#define ELF_MACHINE_ALT1 EM_SCORE_OLD
4444#define ELF_MAXPAGESIZE 0x8000
4445
f3185997 4446#define elf_info_to_howto NULL
07d6d2b8
AM
4447#define elf_info_to_howto_rel _bfd_score_info_to_howto
4448#define elf_backend_relocate_section _bfd_score_elf_relocate_section
4449#define elf_backend_check_relocs _bfd_score_elf_check_relocs
4450#define elf_backend_add_symbol_hook _bfd_score_elf_add_symbol_hook
4451#define elf_backend_symbol_processing _bfd_score_elf_symbol_processing
9838404f
AM
4452#define elf_backend_link_output_symbol_hook \
4453 _bfd_score_elf_link_output_symbol_hook
4454#define elf_backend_section_from_bfd_section \
4455 _bfd_score_elf_section_from_bfd_section
4456#define elf_backend_adjust_dynamic_symbol \
4457 _bfd_score_elf_adjust_dynamic_symbol
4458#define elf_backend_always_size_sections \
4459 _bfd_score_elf_always_size_sections
4460#define elf_backend_size_dynamic_sections \
4461 _bfd_score_elf_size_dynamic_sections
d00dd7dc 4462#define elf_backend_omit_section_dynsym _bfd_elf_omit_section_dynsym_all
9838404f
AM
4463#define elf_backend_create_dynamic_sections \
4464 _bfd_score_elf_create_dynamic_sections
4465#define elf_backend_finish_dynamic_symbol \
4466 _bfd_score_elf_finish_dynamic_symbol
4467#define elf_backend_finish_dynamic_sections \
4468 _bfd_score_elf_finish_dynamic_sections
07d6d2b8
AM
4469#define elf_backend_fake_sections _bfd_score_elf_fake_sections
4470#define elf_backend_section_processing _bfd_score_elf_section_processing
4471#define elf_backend_write_section _bfd_score_elf_write_section
9838404f 4472#define elf_backend_copy_indirect_symbol _bfd_score_elf_copy_indirect_symbol
07d6d2b8
AM
4473#define elf_backend_hide_symbol _bfd_score_elf_hide_symbol
4474#define elf_backend_discard_info _bfd_score_elf_discard_info
9838404f
AM
4475#define elf_backend_ignore_discarded_relocs \
4476 _bfd_score_elf_ignore_discarded_relocs
07d6d2b8
AM
4477#define elf_backend_gc_mark_hook _bfd_score_elf_gc_mark_hook
4478#define elf_backend_grok_prstatus _bfd_score_elf_grok_prstatus
4479#define elf_backend_grok_psinfo _bfd_score_elf_grok_psinfo
4480#define elf_backend_can_gc_sections 1
4481#define elf_backend_want_plt_sym 0
4482#define elf_backend_got_header_size (4 * SCORE_RESERVED_GOTNO)
4483#define elf_backend_plt_header_size 0
0a1b45a2
AM
4484#define elf_backend_collect true
4485#define elf_backend_type_change_ok true
07d6d2b8
AM
4486#define elf_backend_object_p _bfd_score_elf_score_object_p
4487
4488#define bfd_elf32_bfd_reloc_type_lookup elf32_score_reloc_type_lookup
157090f7
AM
4489#define bfd_elf32_bfd_reloc_name_lookup \
4490 elf32_score_reloc_name_lookup
9838404f
AM
4491#define bfd_elf32_bfd_link_hash_table_create elf32_score_link_hash_table_create
4492#define bfd_elf32_bfd_print_private_bfd_data elf32_score_print_private_bfd_data
4493#define bfd_elf32_bfd_merge_private_bfd_data elf32_score_merge_private_bfd_data
07d6d2b8 4494#define bfd_elf32_new_section_hook elf32_score_new_section_hook
1c0d3aa6
NC
4495
4496#include "elf32-target.h"