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

Subversion Repositories open8_urisc

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

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

Line No. Rev Author Line
1 14 khays
/* Xstormy16-specific support for 32-bit ELF.
2 148 khays
   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2010, 2011
3 14 khays
   Free Software Foundation, Inc.
4
 
5
   This file is part of BFD, the Binary File Descriptor library.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software
19
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
 
22
#include "sysdep.h"
23
#include "bfd.h"
24
#include "libbfd.h"
25
#include "elf-bfd.h"
26
#include "elf/xstormy16.h"
27
#include "libiberty.h"
28
 
29
/* Handle the R_XSTORMY16_24 reloc, which has an odd bit arrangement.  */
30
 
31
static bfd_reloc_status_type
32
xstormy16_elf_24_reloc (bfd *abfd,
33
                        arelent *reloc_entry,
34
                        asymbol *symbol,
35
                        void * data,
36
                        asection *input_section,
37
                        bfd *output_bfd,
38
                        char **error_message ATTRIBUTE_UNUSED)
39
{
40
  bfd_vma relocation, x;
41
 
42
  if (output_bfd != NULL)
43
    {
44
      reloc_entry->address += input_section->output_offset;
45
      return bfd_reloc_ok;
46
    }
47
 
48
  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
49
    return bfd_reloc_outofrange;
50
 
51
  if (bfd_is_com_section (symbol->section))
52
    relocation = 0;
53
  else
54
    relocation = symbol->value;
55
 
56
  relocation += symbol->section->output_section->vma;
57
  relocation += symbol->section->output_offset;
58
  relocation += reloc_entry->addend;
59
 
60
  x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
61
  x &= 0x0000ff00;
62
  x |= relocation & 0xff;
63
  x |= (relocation << 8) & 0xffff0000;
64
  bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address);
65
 
66
  if (relocation & ~ (bfd_vma) 0xffffff)
67
    return bfd_reloc_overflow;
68
 
69
  return bfd_reloc_ok;
70
}
71
 
72
static reloc_howto_type xstormy16_elf_howto_table [] =
73
{
74
  /* This reloc does nothing.  */
75
  HOWTO (R_XSTORMY16_NONE,      /* type */
76
         0,                      /* rightshift */
77
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
78
         32,                    /* bitsize */
79
         FALSE,                 /* pc_relative */
80
         0,                      /* bitpos */
81
         complain_overflow_bitfield, /* complain_on_overflow */
82
         bfd_elf_generic_reloc, /* special_function */
83
         "R_XSTORMY16_NONE",    /* name */
84
         FALSE,                 /* partial_inplace */
85
         0,                      /* src_mask */
86
         0,                      /* dst_mask */
87
         FALSE),                /* pcrel_offset */
88
 
89
  /* A 32 bit absolute relocation.  */
90
  HOWTO (R_XSTORMY16_32,        /* type */
91
         0,                      /* rightshift */
92
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
93
         32,                    /* bitsize */
94
         FALSE,                 /* pc_relative */
95
         0,                      /* bitpos */
96
         complain_overflow_dont, /* complain_on_overflow */
97
         bfd_elf_generic_reloc, /* special_function */
98
         "R_XSTORMY16_32",      /* name */
99
         FALSE,                 /* partial_inplace */
100
         0,                      /* src_mask */
101
         0xffffffff,            /* dst_mask */
102
         FALSE),                /* pcrel_offset */
103
 
104
  /* A 16 bit absolute relocation.  */
105
  HOWTO (R_XSTORMY16_16,        /* type */
106
         0,                      /* rightshift */
107
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
108
         16,                    /* bitsize */
109
         FALSE,                 /* pc_relative */
110
         0,                      /* bitpos */
111
         complain_overflow_bitfield, /* complain_on_overflow */
112
         bfd_elf_generic_reloc, /* special_function */
113
         "R_XSTORMY16_16",      /* name */
114
         FALSE,                 /* partial_inplace */
115
         0,                      /* src_mask */
116
         0xffff,                /* dst_mask */
117
         FALSE),                /* pcrel_offset */
118
 
119
  /* An 8 bit absolute relocation.  */
120
  HOWTO (R_XSTORMY16_8,         /* type */
121
         0,                      /* rightshift */
122
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
123
         8,                     /* bitsize */
124
         FALSE,                 /* pc_relative */
125
         0,                      /* bitpos */
126
         complain_overflow_unsigned, /* complain_on_overflow */
127
         bfd_elf_generic_reloc, /* special_function */
128
         "R_XSTORMY16_8",       /* name */
129
         FALSE,                 /* partial_inplace */
130
         0,                      /* src_mask */
131
         0xff,                  /* dst_mask */
132
         FALSE),                /* pcrel_offset */
133
 
134
  /* A 32 bit pc-relative relocation.  */
135
  HOWTO (R_XSTORMY16_PC32,      /* type */
136
         0,                      /* rightshift */
137
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
138
         32,                    /* bitsize */
139
         TRUE,                  /* pc_relative */
140
         0,                      /* bitpos */
141
         complain_overflow_dont, /* complain_on_overflow */
142
         bfd_elf_generic_reloc, /* special_function */
143
         "R_XSTORMY16_PC32",    /* name */
144
         FALSE,                 /* partial_inplace */
145
         0,                      /* src_mask */
146
         0xffffffff,            /* dst_mask */
147
         TRUE),                 /* pcrel_offset */
148
 
149
  /* A 16 bit pc-relative relocation.  */
150
  HOWTO (R_XSTORMY16_PC16,      /* type */
151
         0,                      /* rightshift */
152
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
153
         16,                    /* bitsize */
154
         TRUE,                  /* pc_relative */
155
         0,                      /* bitpos */
156
         complain_overflow_signed, /* complain_on_overflow */
157
         bfd_elf_generic_reloc, /* special_function */
158
         "R_XSTORMY16_PC16",    /* name */
159
         FALSE,                 /* partial_inplace */
160
         0,                      /* src_mask */
161
         0xffffffff,            /* dst_mask */
162
         TRUE),                 /* pcrel_offset */
163
 
164
  /* An 8 bit pc-relative relocation.  */
165
  HOWTO (R_XSTORMY16_PC8,       /* type */
166
         0,                      /* rightshift */
167
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
168
         8,                     /* bitsize */
169
         TRUE,                  /* pc_relative */
170
         0,                      /* bitpos */
171
         complain_overflow_signed, /* complain_on_overflow */
172
         bfd_elf_generic_reloc, /* special_function */
173
         "R_XSTORMY16_PC8",     /* name */
174
         FALSE,                 /* partial_inplace */
175
         0,                      /* src_mask */
176
         0xffffffff,            /* dst_mask */
177
         TRUE),                 /* pcrel_offset */
178
 
179
  /* A 12-bit pc-relative relocation suitable for the branch instructions.  */
180
  HOWTO (R_XSTORMY16_REL_12,    /* type */
181
         1,                     /* rightshift */
182
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
183
         11,                    /* bitsize */
184
         TRUE,                  /* pc_relative */
185
         1,                     /* bitpos */
186
         complain_overflow_signed, /* complain_on_overflow */
187
         bfd_elf_generic_reloc, /* special_function */
188
         "R_XSTORMY16_REL_12",  /* name */
189
         FALSE,                 /* partial_inplace */
190
         0,                      /* src_mask */
191
         0x0ffe,                /* dst_mask */
192
         TRUE),                 /* pcrel_offset */
193
 
194
  /* A 24-bit absolute relocation suitable for the jump instructions.  */
195
  HOWTO (R_XSTORMY16_24,        /* type */
196
         0,                      /* rightshift */
197
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
198
         24,                    /* bitsize */
199
         FALSE,                 /* pc_relative */
200
         0,                      /* bitpos */
201
         complain_overflow_unsigned, /* complain_on_overflow */
202
         xstormy16_elf_24_reloc,        /* special_function */
203
         "R_XSTORMY16_24",      /* name */
204
         TRUE,                  /* partial_inplace */
205
         0,                      /* src_mask */
206
         0xffff00ff,            /* dst_mask */
207
         TRUE),                 /* pcrel_offset */
208
 
209
  /* A 16 bit absolute relocation to a function pointer.  */
210
  HOWTO (R_XSTORMY16_FPTR16,    /* type */
211
         0,                      /* rightshift */
212
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
213
         16,                    /* bitsize */
214
         FALSE,                 /* pc_relative */
215
         0,                      /* bitpos */
216
         complain_overflow_bitfield, /* complain_on_overflow */
217
         bfd_elf_generic_reloc, /* special_function */
218
         "R_XSTORMY16_FPTR16",  /* name */
219
         FALSE,                 /* partial_inplace */
220
         0,                      /* src_mask */
221
         0xffffffff,            /* dst_mask */
222
         FALSE),                /* pcrel_offset */
223
 
224
  /* Low order 16 bit value of a high memory address.  */
225
  HOWTO (R_XSTORMY16_LO16,      /* type */
226
         0,                      /* rightshift */
227
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
228
         16,                    /* bitsize */
229
         FALSE,                 /* pc_relative */
230
         0,                      /* bitpos */
231
         complain_overflow_dont, /* complain_on_overflow */
232
         bfd_elf_generic_reloc, /* special_function */
233
         "R_XSTORMY16_LO16",    /* name */
234
         FALSE,                 /* partial_inplace */
235
         0,                      /* src_mask */
236
         0xffff,                /* dst_mask */
237
         FALSE),                /* pcrel_offset */
238
 
239
  /* High order 16 bit value of a high memory address.  */
240
  HOWTO (R_XSTORMY16_HI16,      /* type */
241
         16,                    /* rightshift */
242
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
243
         16,                    /* bitsize */
244
         FALSE,                 /* pc_relative */
245
         0,                      /* bitpos */
246
         complain_overflow_dont, /* complain_on_overflow */
247
         bfd_elf_generic_reloc, /* special_function */
248
         "R_XSTORMY16_HI16",    /* name */
249
         FALSE,                 /* partial_inplace */
250
         0,                      /* src_mask */
251
         0xffff,                /* dst_mask */
252
         FALSE),                /* pcrel_offset */
253
 
254
  /* A 12 bit absolute relocation.  */
255
  HOWTO (R_XSTORMY16_12,        /* type */
256
         0,                      /* rightshift */
257
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
258
         12,                    /* bitsize */
259
         FALSE,                 /* pc_relative */
260
         0,                      /* bitpos */
261
         complain_overflow_signed, /* complain_on_overflow */
262
         bfd_elf_generic_reloc, /* special_function */
263
         "R_XSTORMY16_12",      /* name */
264
         FALSE,                 /* partial_inplace */
265
         0x0000,                /* src_mask */
266
         0x0fff,                /* dst_mask */
267
         FALSE),                /* pcrel_offset */
268
};
269
 
270
static reloc_howto_type xstormy16_elf_howto_table2 [] =
271
{
272
  /* GNU extension to record C++ vtable hierarchy */
273
  HOWTO (R_XSTORMY16_GNU_VTINHERIT, /* type */
274
         0,                     /* rightshift */
275
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
276
         0,                     /* bitsize */
277
         FALSE,                 /* pc_relative */
278
         0,                     /* bitpos */
279
         complain_overflow_dont, /* complain_on_overflow */
280
         NULL,                  /* special_function */
281
         "R_XSTORMY16_GNU_VTINHERIT", /* name */
282
         FALSE,                 /* partial_inplace */
283
         0,                     /* src_mask */
284
         0,                     /* dst_mask */
285
         FALSE),                /* pcrel_offset */
286
 
287
  /* GNU extension to record C++ vtable member usage */
288
  HOWTO (R_XSTORMY16_GNU_VTENTRY,     /* type */
289
         0,                     /* rightshift */
290
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
291
         0,                     /* bitsize */
292
         FALSE,                 /* pc_relative */
293
         0,                     /* bitpos */
294
         complain_overflow_dont, /* complain_on_overflow */
295
         _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
296
         "R_XSTORMY16_GNU_VTENTRY",   /* name */
297
         FALSE,                 /* partial_inplace */
298
         0,                     /* src_mask */
299
         0,                     /* dst_mask */
300
         FALSE),                /* pcrel_offset */
301
 
302
};
303
 
304
/* Map BFD reloc types to XSTORMY16 ELF reloc types.  */
305
 
306
typedef struct xstormy16_reloc_map
307
{
308
  bfd_reloc_code_real_type  bfd_reloc_val;
309
  unsigned int              xstormy16_reloc_val;
310
  reloc_howto_type *        table;
311
} reloc_map;
312
 
313
static const reloc_map xstormy16_reloc_map [] =
314
{
315
  { BFD_RELOC_NONE,                 R_XSTORMY16_NONE,          xstormy16_elf_howto_table },
316
  { BFD_RELOC_32,                   R_XSTORMY16_32,            xstormy16_elf_howto_table },
317
  { BFD_RELOC_16,                   R_XSTORMY16_16,            xstormy16_elf_howto_table },
318
  { BFD_RELOC_8,                    R_XSTORMY16_8,             xstormy16_elf_howto_table },
319
  { BFD_RELOC_32_PCREL,             R_XSTORMY16_PC32,          xstormy16_elf_howto_table },
320
  { BFD_RELOC_16_PCREL,             R_XSTORMY16_PC16,          xstormy16_elf_howto_table },
321
  { BFD_RELOC_8_PCREL,              R_XSTORMY16_PC8,           xstormy16_elf_howto_table },
322
  { BFD_RELOC_XSTORMY16_REL_12,     R_XSTORMY16_REL_12,        xstormy16_elf_howto_table },
323
  { BFD_RELOC_XSTORMY16_24,         R_XSTORMY16_24,            xstormy16_elf_howto_table },
324
  { BFD_RELOC_XSTORMY16_FPTR16,     R_XSTORMY16_FPTR16,        xstormy16_elf_howto_table },
325
  { BFD_RELOC_LO16,                 R_XSTORMY16_LO16,          xstormy16_elf_howto_table },
326
  { BFD_RELOC_HI16,                 R_XSTORMY16_HI16,          xstormy16_elf_howto_table },
327
  { BFD_RELOC_XSTORMY16_12,         R_XSTORMY16_12,            xstormy16_elf_howto_table },
328
  { BFD_RELOC_VTABLE_INHERIT,       R_XSTORMY16_GNU_VTINHERIT, xstormy16_elf_howto_table2 },
329
  { BFD_RELOC_VTABLE_ENTRY,         R_XSTORMY16_GNU_VTENTRY,   xstormy16_elf_howto_table2 },
330
};
331
 
332
static reloc_howto_type *
333
xstormy16_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
334
                             bfd_reloc_code_real_type code)
335
{
336
  unsigned int i;
337
 
338
  for (i = ARRAY_SIZE (xstormy16_reloc_map); --i;)
339
    {
340
      const reloc_map * entry;
341
 
342
      entry = xstormy16_reloc_map + i;
343
 
344
      if (entry->bfd_reloc_val == code)
345
        return entry->table + (entry->xstormy16_reloc_val
346
                               - entry->table[0].type);
347
    }
348
 
349
  return NULL;
350
}
351
 
352
static reloc_howto_type *
353
xstormy16_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
354
                             const char *r_name)
355
{
356
  unsigned int i;
357
 
358
  for (i = 0;
359
       i < (sizeof (xstormy16_elf_howto_table)
360
            / sizeof (xstormy16_elf_howto_table[0]));
361
       i++)
362
    if (xstormy16_elf_howto_table[i].name != NULL
363
        && strcasecmp (xstormy16_elf_howto_table[i].name, r_name) == 0)
364
      return &xstormy16_elf_howto_table[i];
365
 
366
  for (i = 0;
367
       i < (sizeof (xstormy16_elf_howto_table2)
368
            / sizeof (xstormy16_elf_howto_table2[0]));
369
       i++)
370
    if (xstormy16_elf_howto_table2[i].name != NULL
371
        && strcasecmp (xstormy16_elf_howto_table2[i].name, r_name) == 0)
372
      return &xstormy16_elf_howto_table2[i];
373
 
374
  return NULL;
375
}
376
 
377
/* Set the howto pointer for an XSTORMY16 ELF reloc.  */
378
 
379
static void
380
xstormy16_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
381
                              arelent * cache_ptr,
382
                              Elf_Internal_Rela * dst)
383
{
384
  unsigned int r_type = ELF32_R_TYPE (dst->r_info);
385
 
386
  if (r_type <= (unsigned int) R_XSTORMY16_12)
387
    cache_ptr->howto = &xstormy16_elf_howto_table [r_type];
388
  else if (r_type - R_XSTORMY16_GNU_VTINHERIT
389
           <= (unsigned int) R_XSTORMY16_GNU_VTENTRY)
390
    cache_ptr->howto
391
      = &xstormy16_elf_howto_table2 [r_type - R_XSTORMY16_GNU_VTINHERIT];
392
  else
393
    abort ();
394
}
395
 
396
/* We support 16-bit pointers to code above 64k by generating a thunk
397
   below 64k containing a JMPF instruction to the final address.  We
398
   cannot, unfortunately, minimize the number of thunks unless the
399
   -relax switch is given, as otherwise we have no idea where the
400
   sections will fall in the address space.  */
401
 
402
static bfd_boolean
403
xstormy16_elf_check_relocs (bfd *abfd,
404
                            struct bfd_link_info *info,
405
                            asection *sec,
406
                            const Elf_Internal_Rela *relocs)
407
{
408
  const Elf_Internal_Rela *rel, *relend;
409
  struct elf_link_hash_entry **sym_hashes;
410
  Elf_Internal_Shdr *symtab_hdr;
411
  bfd_vma *local_plt_offsets;
412
  asection *splt;
413
  bfd *dynobj;
414
 
415
  if (info->relocatable)
416
    return TRUE;
417
 
418
  symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
419
  sym_hashes = elf_sym_hashes (abfd);
420
  local_plt_offsets = elf_local_got_offsets (abfd);
421
  splt = NULL;
422
  dynobj = elf_hash_table(info)->dynobj;
423
 
424
  relend = relocs + sec->reloc_count;
425
  for (rel = relocs; rel < relend; ++rel)
426
    {
427
      unsigned long r_symndx;
428
      struct elf_link_hash_entry *h;
429
      bfd_vma *offset;
430
 
431
      r_symndx = ELF32_R_SYM (rel->r_info);
432
      if (r_symndx < symtab_hdr->sh_info)
433
        h = NULL;
434
      else
435
        {
436
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
437
          while (h->root.type == bfd_link_hash_indirect
438
                 || h->root.type == bfd_link_hash_warning)
439
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
440
        }
441
 
442
      switch (ELF32_R_TYPE (rel->r_info))
443
        {
444
          /* This relocation describes a 16-bit pointer to a function.
445
             We may need to allocate a thunk in low memory; reserve memory
446
             for it now.  */
447
        case R_XSTORMY16_FPTR16:
448
          if (rel->r_addend != 0)
449
            {
450
              (*info->callbacks->warning)
451
                (info, _("non-zero addend in @fptr reloc"), 0,
452
                 abfd, 0, 0);
453
            }
454
 
455
          if (dynobj == NULL)
456
            elf_hash_table (info)->dynobj = dynobj = abfd;
457
          if (splt == NULL)
458
            {
459
              splt = bfd_get_section_by_name (dynobj, ".plt");
460
              if (splt == NULL)
461
                {
462
                  splt = bfd_make_section_with_flags (dynobj, ".plt",
463
                                                      (SEC_ALLOC
464
                                                       | SEC_LOAD
465
                                                       | SEC_HAS_CONTENTS
466
                                                       | SEC_IN_MEMORY
467
                                                       | SEC_LINKER_CREATED
468
                                                       | SEC_READONLY
469
                                                       | SEC_CODE));
470
 
471
                  if (splt == NULL
472
                      || ! bfd_set_section_alignment (dynobj, splt, 1))
473
                    return FALSE;
474
                }
475
            }
476
 
477
          if (h != NULL)
478
            offset = &h->plt.offset;
479
          else
480
            {
481
              if (local_plt_offsets == NULL)
482
                {
483
                  size_t size;
484
                  unsigned int i;
485
 
486
                  size = symtab_hdr->sh_info * sizeof (bfd_vma);
487
                  local_plt_offsets = bfd_alloc (abfd, size);
488
                  if (local_plt_offsets == NULL)
489
                    return FALSE;
490
                  elf_local_got_offsets (abfd) = local_plt_offsets;
491
 
492
                  for (i = 0; i < symtab_hdr->sh_info; i++)
493
                    local_plt_offsets[i] = (bfd_vma) -1;
494
                }
495
              offset = &local_plt_offsets[r_symndx];
496
            }
497
 
498
          if (*offset == (bfd_vma) -1)
499
            {
500
              *offset = splt->size;
501
              splt->size += 4;
502
            }
503
          break;
504
 
505
          /* This relocation describes the C++ object vtable hierarchy.
506
             Reconstruct it for later use during GC.  */
507
        case R_XSTORMY16_GNU_VTINHERIT:
508
          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
509
            return FALSE;
510
          break;
511
 
512
          /* This relocation describes which C++ vtable entries are actually
513
             used.  Record for later use during GC.  */
514
        case R_XSTORMY16_GNU_VTENTRY:
515
          BFD_ASSERT (h != NULL);
516
          if (h != NULL
517
              && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
518
            return FALSE;
519
          break;
520
        }
521
    }
522
 
523
  return TRUE;
524
}
525
 
526
/* A subroutine of xstormy16_elf_relax_section.  If the global symbol H
527
   is within the low 64k, remove any entry for it in the plt.  */
528
 
529
struct relax_plt_data
530
{
531
  asection *splt;
532
  bfd_boolean *again;
533
};
534
 
535
static bfd_boolean
536
xstormy16_relax_plt_check (struct elf_link_hash_entry *h, void * xdata)
537
{
538
  struct relax_plt_data *data = (struct relax_plt_data *) xdata;
539
 
540
  if (h->plt.offset != (bfd_vma) -1)
541
    {
542
      bfd_vma address;
543
 
544
      if (h->root.type == bfd_link_hash_undefined
545
          || h->root.type == bfd_link_hash_undefweak)
546
        address = 0;
547
      else
548
        address = (h->root.u.def.section->output_section->vma
549
                   + h->root.u.def.section->output_offset
550
                   + h->root.u.def.value);
551
 
552
      if (address <= 0xffff)
553
        {
554
          h->plt.offset = -1;
555
          data->splt->size -= 4;
556
          *data->again = TRUE;
557
        }
558
    }
559
 
560
  return TRUE;
561
}
562
 
563
/* A subroutine of xstormy16_elf_relax_section.  If the global symbol H
564
   previously had a plt entry, give it a new entry offset.  */
565
 
566
static bfd_boolean
567
xstormy16_relax_plt_realloc (struct elf_link_hash_entry *h, void * xdata)
568
{
569
  bfd_vma *entry = (bfd_vma *) xdata;
570
 
571
  if (h->plt.offset != (bfd_vma) -1)
572
    {
573
      h->plt.offset = *entry;
574
      *entry += 4;
575
    }
576
 
577
  return TRUE;
578
}
579
 
580
static bfd_boolean
581
xstormy16_elf_relax_section (bfd *dynobj,
582
                             asection *splt,
583
                             struct bfd_link_info *info,
584
                             bfd_boolean *again)
585
{
586
  struct relax_plt_data relax_plt_data;
587
  bfd *ibfd;
588
 
589
  /* Assume nothing changes.  */
590
  *again = FALSE;
591
 
592
  if (info->relocatable)
593
    return TRUE;
594
 
595
  /* We only relax the .plt section at the moment.  */
596
  if (dynobj != elf_hash_table (info)->dynobj
597
      || strcmp (splt->name, ".plt") != 0)
598
    return TRUE;
599
 
600
  /* Quick check for an empty plt.  */
601
  if (splt->size == 0)
602
    return TRUE;
603
 
604
  /* Map across all global symbols; see which ones happen to
605
     fall in the low 64k.  */
606
  relax_plt_data.splt = splt;
607
  relax_plt_data.again = again;
608
  elf_link_hash_traverse (elf_hash_table (info), xstormy16_relax_plt_check,
609
                          &relax_plt_data);
610
 
611
  /* Likewise for local symbols, though that's somewhat less convenient
612
     as we have to walk the list of input bfds and swap in symbol data.  */
613
  for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
614
    {
615
      bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
616
      Elf_Internal_Shdr *symtab_hdr;
617
      Elf_Internal_Sym *isymbuf = NULL;
618
      unsigned int idx;
619
 
620
      if (! local_plt_offsets)
621
        continue;
622
 
623
      symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
624
      if (symtab_hdr->sh_info != 0)
625
        {
626
          isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
627
          if (isymbuf == NULL)
628
            isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
629
                                            symtab_hdr->sh_info, 0,
630
                                            NULL, NULL, NULL);
631
          if (isymbuf == NULL)
632
            return FALSE;
633
        }
634
 
635
      for (idx = 0; idx < symtab_hdr->sh_info; ++idx)
636
        {
637
          Elf_Internal_Sym *isym;
638
          asection *tsec;
639
          bfd_vma address;
640
 
641
          if (local_plt_offsets[idx] == (bfd_vma) -1)
642
            continue;
643
 
644
          isym = &isymbuf[idx];
645
          if (isym->st_shndx == SHN_UNDEF)
646
            continue;
647
          else if (isym->st_shndx == SHN_ABS)
648
            tsec = bfd_abs_section_ptr;
649
          else if (isym->st_shndx == SHN_COMMON)
650
            tsec = bfd_com_section_ptr;
651
          else
652
            tsec = bfd_section_from_elf_index (ibfd, isym->st_shndx);
653
 
654
          address = (tsec->output_section->vma
655
                     + tsec->output_offset
656
                     + isym->st_value);
657
          if (address <= 0xffff)
658
            {
659
              local_plt_offsets[idx] = -1;
660
              splt->size -= 4;
661
              *again = TRUE;
662
            }
663
        }
664
 
665
      if (isymbuf != NULL
666
          && symtab_hdr->contents != (unsigned char *) isymbuf)
667
        {
668
          if (! info->keep_memory)
669
            free (isymbuf);
670
          else
671
            {
672
              /* Cache the symbols for elf_link_input_bfd.  */
673
              symtab_hdr->contents = (unsigned char *) isymbuf;
674
            }
675
        }
676
    }
677
 
678
  /* If we changed anything, walk the symbols again to reallocate
679
     .plt entry addresses.  */
680
  if (*again && splt->size > 0)
681
    {
682
      bfd_vma entry = 0;
683
 
684
      elf_link_hash_traverse (elf_hash_table (info),
685
                              xstormy16_relax_plt_realloc, &entry);
686
 
687
      for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
688
        {
689
          bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
690
          unsigned int nlocals = elf_tdata (ibfd)->symtab_hdr.sh_info;
691
          unsigned int idx;
692
 
693
          if (! local_plt_offsets)
694
            continue;
695
 
696
          for (idx = 0; idx < nlocals; ++idx)
697
            if (local_plt_offsets[idx] != (bfd_vma) -1)
698
              {
699
                local_plt_offsets[idx] = entry;
700
                entry += 4;
701
              }
702
        }
703
    }
704
 
705
  return TRUE;
706
}
707
 
708
static bfd_boolean
709
xstormy16_elf_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
710
                                    struct bfd_link_info *info)
711
{
712
  bfd *dynobj;
713
  asection *splt;
714
 
715
  if (info->relocatable)
716
    return TRUE;
717
 
718
  dynobj = elf_hash_table (info)->dynobj;
719
  if (dynobj == NULL)
720
    return TRUE;
721
 
722
  splt = bfd_get_section_by_name (dynobj, ".plt");
723
  BFD_ASSERT (splt != NULL);
724
 
725
  splt->contents = bfd_zalloc (dynobj, splt->size);
726
  if (splt->contents == NULL)
727
    return FALSE;
728
 
729
  return TRUE;
730
}
731
 
732
/* Relocate an XSTORMY16 ELF section.
733
 
734
   The RELOCATE_SECTION function is called by the new ELF backend linker
735
   to handle the relocations for a section.
736
 
737
   The relocs are always passed as Rela structures; if the section
738
   actually uses Rel structures, the r_addend field will always be
739
   zero.
740
 
741
   This function is responsible for adjusting the section contents as
742
   necessary, and (if using Rela relocs and generating a relocatable
743
   output file) adjusting the reloc addend as necessary.
744
 
745
   This function does not have to worry about setting the reloc
746
   address or the reloc symbol index.
747
 
748
   LOCAL_SYMS is a pointer to the swapped in local symbols.
749
 
750
   LOCAL_SECTIONS is an array giving the section in the input file
751
   corresponding to the st_shndx field of each local symbol.
752
 
753
   The global hash table entry for the global symbols can be found
754
   via elf_sym_hashes (input_bfd).
755
 
756
   When generating relocatable output, this function must handle
757
   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
758
   going to be the section symbol corresponding to the output
759
   section, which means that the addend must be adjusted
760
   accordingly.  */
761
 
762
static bfd_boolean
763
xstormy16_elf_relocate_section (bfd *                   output_bfd ATTRIBUTE_UNUSED,
764
                                struct bfd_link_info *  info,
765
                                bfd *                   input_bfd,
766
                                asection *              input_section,
767
                                bfd_byte *              contents,
768
                                Elf_Internal_Rela *     relocs,
769
                                Elf_Internal_Sym *      local_syms,
770
                                asection **             local_sections)
771
{
772
  Elf_Internal_Shdr *           symtab_hdr;
773
  struct elf_link_hash_entry ** sym_hashes;
774
  Elf_Internal_Rela *           rel;
775
  Elf_Internal_Rela *           relend;
776
  bfd *dynobj;
777
  asection *splt;
778
 
779
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
780
  sym_hashes = elf_sym_hashes (input_bfd);
781
  relend     = relocs + input_section->reloc_count;
782
 
783
  dynobj = elf_hash_table (info)->dynobj;
784
  splt = NULL;
785
  if (dynobj != NULL)
786
    splt = bfd_get_section_by_name (dynobj, ".plt");
787
 
788
  for (rel = relocs; rel < relend; rel ++)
789
    {
790
      reloc_howto_type *           howto;
791
      unsigned long                r_symndx;
792
      Elf_Internal_Sym *           sym;
793
      asection *                   sec;
794
      struct elf_link_hash_entry * h;
795
      bfd_vma                      relocation;
796
      bfd_reloc_status_type        r;
797
      const char *                 name = NULL;
798
      int                          r_type;
799
 
800
      r_type = ELF32_R_TYPE (rel->r_info);
801
 
802
      if (   r_type == R_XSTORMY16_GNU_VTINHERIT
803
          || r_type == R_XSTORMY16_GNU_VTENTRY)
804
        continue;
805
 
806
      r_symndx = ELF32_R_SYM (rel->r_info);
807
      howto  = xstormy16_elf_howto_table + ELF32_R_TYPE (rel->r_info);
808
      h      = NULL;
809
      sym    = NULL;
810
      sec    = NULL;
811
 
812
      if (r_symndx < symtab_hdr->sh_info)
813
        {
814
          sym = local_syms + r_symndx;
815
          sec = local_sections [r_symndx];
816
          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
817
        }
818
      else
819
        {
820
          bfd_boolean unresolved_reloc, warned;
821
 
822
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
823
                                   r_symndx, symtab_hdr, sym_hashes,
824
                                   h, sec, relocation,
825
                                   unresolved_reloc, warned);
826
        }
827
 
828
      if (sec != NULL && elf_discarded_section (sec))
829
        RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
830
                                         rel, relend, howto, contents);
831
 
832
      if (info->relocatable)
833
        continue;
834
 
835
      if (h != NULL)
836
        name = h->root.root.string;
837
      else
838
        {
839
          name = (bfd_elf_string_from_elf_section
840
                  (input_bfd, symtab_hdr->sh_link, sym->st_name));
841
          if (name == NULL || *name == '\0')
842
            name = bfd_section_name (input_bfd, sec);
843
        }
844
 
845
      switch (ELF32_R_TYPE (rel->r_info))
846
        {
847
        case R_XSTORMY16_24:
848
          {
849
            bfd_vma reloc = relocation + rel->r_addend;
850
            unsigned int x;
851
 
852
            x = bfd_get_32 (input_bfd, contents + rel->r_offset);
853
            x &= 0x0000ff00;
854
            x |= reloc & 0xff;
855
            x |= (reloc << 8) & 0xffff0000;
856
            bfd_put_32 (input_bfd, x, contents + rel->r_offset);
857
 
858
            if (reloc & ~0xffffff)
859
              r = bfd_reloc_overflow;
860
            else
861
              r = bfd_reloc_ok;
862
            break;
863
          }
864
 
865
        case R_XSTORMY16_FPTR16:
866
          {
867
            bfd_vma *plt_offset;
868
 
869
            if (h != NULL)
870
              plt_offset = &h->plt.offset;
871
            else
872
              plt_offset = elf_local_got_offsets (input_bfd) + r_symndx;
873
 
874
            if (relocation <= 0xffff)
875
              {
876
                /* If the symbol is in range for a 16-bit address, we should
877
                   have deallocated the plt entry in relax_section.  */
878
                BFD_ASSERT (*plt_offset == (bfd_vma) -1);
879
              }
880
            else
881
              {
882
                /* If the symbol is out of range for a 16-bit address,
883
                   we must have allocated a plt entry.  */
884
                BFD_ASSERT (*plt_offset != (bfd_vma) -1);
885
 
886
                /* If this is the first time we've processed this symbol,
887
                   fill in the plt entry with the correct symbol address.  */
888
                if ((*plt_offset & 1) == 0)
889
                  {
890
                    unsigned int x;
891
 
892
                    x = 0x00000200;  /* jmpf */
893
                    x |= relocation & 0xff;
894
                    x |= (relocation << 8) & 0xffff0000;
895
                    bfd_put_32 (input_bfd, x, splt->contents + *plt_offset);
896
                    *plt_offset |= 1;
897
                  }
898
 
899
                relocation = (splt->output_section->vma
900
                              + splt->output_offset
901
                              + (*plt_offset & -2));
902
              }
903
            r = _bfd_final_link_relocate (howto, input_bfd, input_section,
904
                                          contents, rel->r_offset,
905
                                          relocation, 0);
906
            break;
907
          }
908
 
909
        default:
910
          r = _bfd_final_link_relocate (howto, input_bfd, input_section,
911
                                        contents, rel->r_offset,
912
                                        relocation, rel->r_addend);
913
          break;
914
        }
915
 
916
      if (r != bfd_reloc_ok)
917
        {
918
          const char * msg = NULL;
919
 
920
          switch (r)
921
            {
922
            case bfd_reloc_overflow:
923
              r = info->callbacks->reloc_overflow
924
                (info, (h ? &h->root : NULL), name, howto->name,
925
                 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
926
              break;
927
 
928
            case bfd_reloc_undefined:
929
              r = info->callbacks->undefined_symbol
930
                (info, name, input_bfd, input_section, rel->r_offset,
931
                 TRUE);
932
              break;
933
 
934
            case bfd_reloc_outofrange:
935
              msg = _("internal error: out of range error");
936
              break;
937
 
938
            case bfd_reloc_notsupported:
939
              msg = _("internal error: unsupported relocation error");
940
              break;
941
 
942
            case bfd_reloc_dangerous:
943
              msg = _("internal error: dangerous relocation");
944
              break;
945
 
946
            default:
947
              msg = _("internal error: unknown error");
948
              break;
949
            }
950
 
951
          if (msg)
952
            r = info->callbacks->warning
953
              (info, msg, name, input_bfd, input_section, rel->r_offset);
954
 
955
          if (! r)
956
            return FALSE;
957
        }
958
    }
959
 
960
  return TRUE;
961
}
962
 
963
/* This must exist if dynobj is ever set.  */
964
 
965
static bfd_boolean
966
xstormy16_elf_finish_dynamic_sections (bfd *abfd ATTRIBUTE_UNUSED,
967
                                       struct bfd_link_info *info)
968
{
969
  bfd *dynobj;
970
  asection *splt;
971
 
972
  /* As an extra sanity check, verify that all plt entries have
973
     been filled in.  */
974
 
975
  if ((dynobj = elf_hash_table (info)->dynobj) != NULL
976
      && (splt = bfd_get_section_by_name (dynobj, ".plt")) != NULL)
977
    {
978
      bfd_byte *contents = splt->contents;
979
      unsigned int i, size = splt->size;
980
 
981
      for (i = 0; i < size; i += 4)
982
        {
983
          unsigned int x = bfd_get_32 (dynobj, contents + i);
984
 
985
          BFD_ASSERT (x != 0);
986
        }
987
    }
988
 
989
  return TRUE;
990
}
991
 
992
/* Return the section that should be marked against GC for a given
993
   relocation.  */
994
 
995
static asection *
996
xstormy16_elf_gc_mark_hook (asection *sec,
997
                            struct bfd_link_info *info,
998
                            Elf_Internal_Rela *rel,
999
                            struct elf_link_hash_entry *h,
1000
                            Elf_Internal_Sym *sym)
1001
{
1002
  if (h != NULL)
1003
    switch (ELF32_R_TYPE (rel->r_info))
1004
      {
1005
      case R_XSTORMY16_GNU_VTINHERIT:
1006
      case R_XSTORMY16_GNU_VTENTRY:
1007
        return NULL;
1008
      }
1009
 
1010
  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
1011
}
1012
 
1013
#define ELF_ARCH                bfd_arch_xstormy16
1014
#define ELF_MACHINE_CODE        EM_XSTORMY16
1015
#define ELF_MAXPAGESIZE         0x100
1016
 
1017
#define TARGET_LITTLE_SYM       bfd_elf32_xstormy16_vec
1018
#define TARGET_LITTLE_NAME      "elf32-xstormy16"
1019
 
1020
#define elf_info_to_howto_rel                   NULL
1021
#define elf_info_to_howto                       xstormy16_info_to_howto_rela
1022
#define elf_backend_relocate_section            xstormy16_elf_relocate_section
1023
#define elf_backend_gc_mark_hook                xstormy16_elf_gc_mark_hook
1024
#define elf_backend_check_relocs                xstormy16_elf_check_relocs
1025
#define elf_backend_always_size_sections \
1026
  xstormy16_elf_always_size_sections
1027
#define elf_backend_omit_section_dynsym \
1028
  ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
1029
#define elf_backend_finish_dynamic_sections \
1030
  xstormy16_elf_finish_dynamic_sections
1031
 
1032
#define elf_backend_can_gc_sections             1
1033
#define elf_backend_rela_normal                 1
1034
 
1035
#define bfd_elf32_bfd_reloc_type_lookup         xstormy16_reloc_type_lookup
1036
#define bfd_elf32_bfd_reloc_name_lookup \
1037
  xstormy16_reloc_name_lookup
1038
#define bfd_elf32_bfd_relax_section             xstormy16_elf_relax_section
1039
 
1040
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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