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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [elf32-score7.c] - Blame information for rev 118

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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