OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [bfd/] [elf32-score.c] - Blame information for rev 225

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.