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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.18.50/] [bfd/] [elf32-xstormy16.c] - Blame information for rev 156

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* Xstormy16-specific support for 32-bit ELF.
2
   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
3
   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->root.type == bfd_link_hash_warning)
541
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
542
 
543
  if (h->plt.offset != (bfd_vma) -1)
544
    {
545
      bfd_vma address;
546
 
547
      if (h->root.type == bfd_link_hash_undefined
548
          || h->root.type == bfd_link_hash_undefweak)
549
        address = 0;
550
      else
551
        address = (h->root.u.def.section->output_section->vma
552
                   + h->root.u.def.section->output_offset
553
                   + h->root.u.def.value);
554
 
555
      if (address <= 0xffff)
556
        {
557
          h->plt.offset = -1;
558
          data->splt->size -= 4;
559
          *data->again = TRUE;
560
        }
561
    }
562
 
563
  return TRUE;
564
}
565
 
566
/* A subroutine of xstormy16_elf_relax_section.  If the global symbol H
567
   previously had a plt entry, give it a new entry offset.  */
568
 
569
static bfd_boolean
570
xstormy16_relax_plt_realloc (struct elf_link_hash_entry *h, void * xdata)
571
{
572
  bfd_vma *entry = (bfd_vma *) xdata;
573
 
574
  if (h->root.type == bfd_link_hash_warning)
575
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
576
 
577
  if (h->plt.offset != (bfd_vma) -1)
578
    {
579
      h->plt.offset = *entry;
580
      *entry += 4;
581
    }
582
 
583
  return TRUE;
584
}
585
 
586
static bfd_boolean
587
xstormy16_elf_relax_section (bfd *dynobj,
588
                             asection *splt,
589
                             struct bfd_link_info *info,
590
                             bfd_boolean *again)
591
{
592
  struct relax_plt_data relax_plt_data;
593
  bfd *ibfd;
594
 
595
  /* Assume nothing changes.  */
596
  *again = FALSE;
597
 
598
  if (info->relocatable)
599
    return TRUE;
600
 
601
  /* We only relax the .plt section at the moment.  */
602
  if (dynobj != elf_hash_table (info)->dynobj
603
      || strcmp (splt->name, ".plt") != 0)
604
    return TRUE;
605
 
606
  /* Quick check for an empty plt.  */
607
  if (splt->size == 0)
608
    return TRUE;
609
 
610
  /* Map across all global symbols; see which ones happen to
611
     fall in the low 64k.  */
612
  relax_plt_data.splt = splt;
613
  relax_plt_data.again = again;
614
  elf_link_hash_traverse (elf_hash_table (info), xstormy16_relax_plt_check,
615
                          &relax_plt_data);
616
 
617
  /* Likewise for local symbols, though that's somewhat less convenient
618
     as we have to walk the list of input bfds and swap in symbol data.  */
619
  for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
620
    {
621
      bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
622
      Elf_Internal_Shdr *symtab_hdr;
623
      Elf_Internal_Sym *isymbuf = NULL;
624
      unsigned int idx;
625
 
626
      if (! local_plt_offsets)
627
        continue;
628
 
629
      symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
630
      if (symtab_hdr->sh_info != 0)
631
        {
632
          isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
633
          if (isymbuf == NULL)
634
            isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
635
                                            symtab_hdr->sh_info, 0,
636
                                            NULL, NULL, NULL);
637
          if (isymbuf == NULL)
638
            return FALSE;
639
        }
640
 
641
      for (idx = 0; idx < symtab_hdr->sh_info; ++idx)
642
        {
643
          Elf_Internal_Sym *isym;
644
          asection *tsec;
645
          bfd_vma address;
646
 
647
          if (local_plt_offsets[idx] == (bfd_vma) -1)
648
            continue;
649
 
650
          isym = &isymbuf[idx];
651
          if (isym->st_shndx == SHN_UNDEF)
652
            continue;
653
          else if (isym->st_shndx == SHN_ABS)
654
            tsec = bfd_abs_section_ptr;
655
          else if (isym->st_shndx == SHN_COMMON)
656
            tsec = bfd_com_section_ptr;
657
          else
658
            tsec = bfd_section_from_elf_index (ibfd, isym->st_shndx);
659
 
660
          address = (tsec->output_section->vma
661
                     + tsec->output_offset
662
                     + isym->st_value);
663
          if (address <= 0xffff)
664
            {
665
              local_plt_offsets[idx] = -1;
666
              splt->size -= 4;
667
              *again = TRUE;
668
            }
669
        }
670
 
671
      if (isymbuf != NULL
672
          && symtab_hdr->contents != (unsigned char *) isymbuf)
673
        {
674
          if (! info->keep_memory)
675
            free (isymbuf);
676
          else
677
            {
678
              /* Cache the symbols for elf_link_input_bfd.  */
679
              symtab_hdr->contents = (unsigned char *) isymbuf;
680
            }
681
        }
682
    }
683
 
684
  /* If we changed anything, walk the symbols again to reallocate
685
     .plt entry addresses.  */
686
  if (*again && splt->size > 0)
687
    {
688
      bfd_vma entry = 0;
689
 
690
      elf_link_hash_traverse (elf_hash_table (info),
691
                              xstormy16_relax_plt_realloc, &entry);
692
 
693
      for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
694
        {
695
          bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
696
          unsigned int nlocals = elf_tdata (ibfd)->symtab_hdr.sh_info;
697
          unsigned int idx;
698
 
699
          if (! local_plt_offsets)
700
            continue;
701
 
702
          for (idx = 0; idx < nlocals; ++idx)
703
            if (local_plt_offsets[idx] != (bfd_vma) -1)
704
              {
705
                local_plt_offsets[idx] = entry;
706
                entry += 4;
707
              }
708
        }
709
    }
710
 
711
  return TRUE;
712
}
713
 
714
static bfd_boolean
715
xstormy16_elf_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
716
                                    struct bfd_link_info *info)
717
{
718
  bfd *dynobj;
719
  asection *splt;
720
 
721
  if (info->relocatable)
722
    return TRUE;
723
 
724
  dynobj = elf_hash_table (info)->dynobj;
725
  if (dynobj == NULL)
726
    return TRUE;
727
 
728
  splt = bfd_get_section_by_name (dynobj, ".plt");
729
  BFD_ASSERT (splt != NULL);
730
 
731
  splt->contents = bfd_zalloc (dynobj, splt->size);
732
  if (splt->contents == NULL)
733
    return FALSE;
734
 
735
  return TRUE;
736
}
737
 
738
/* Relocate an XSTORMY16 ELF section.
739
 
740
   The RELOCATE_SECTION function is called by the new ELF backend linker
741
   to handle the relocations for a section.
742
 
743
   The relocs are always passed as Rela structures; if the section
744
   actually uses Rel structures, the r_addend field will always be
745
   zero.
746
 
747
   This function is responsible for adjusting the section contents as
748
   necessary, and (if using Rela relocs and generating a relocatable
749
   output file) adjusting the reloc addend as necessary.
750
 
751
   This function does not have to worry about setting the reloc
752
   address or the reloc symbol index.
753
 
754
   LOCAL_SYMS is a pointer to the swapped in local symbols.
755
 
756
   LOCAL_SECTIONS is an array giving the section in the input file
757
   corresponding to the st_shndx field of each local symbol.
758
 
759
   The global hash table entry for the global symbols can be found
760
   via elf_sym_hashes (input_bfd).
761
 
762
   When generating relocatable output, this function must handle
763
   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
764
   going to be the section symbol corresponding to the output
765
   section, which means that the addend must be adjusted
766
   accordingly.  */
767
 
768
static bfd_boolean
769
xstormy16_elf_relocate_section (bfd *                   output_bfd ATTRIBUTE_UNUSED,
770
                                struct bfd_link_info *  info,
771
                                bfd *                   input_bfd,
772
                                asection *              input_section,
773
                                bfd_byte *              contents,
774
                                Elf_Internal_Rela *     relocs,
775
                                Elf_Internal_Sym *      local_syms,
776
                                asection **             local_sections)
777
{
778
  Elf_Internal_Shdr *           symtab_hdr;
779
  struct elf_link_hash_entry ** sym_hashes;
780
  Elf_Internal_Rela *           rel;
781
  Elf_Internal_Rela *           relend;
782
  bfd *dynobj;
783
  asection *splt;
784
 
785
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
786
  sym_hashes = elf_sym_hashes (input_bfd);
787
  relend     = relocs + input_section->reloc_count;
788
 
789
  dynobj = elf_hash_table (info)->dynobj;
790
  splt = NULL;
791
  if (dynobj != NULL)
792
    splt = bfd_get_section_by_name (dynobj, ".plt");
793
 
794
  for (rel = relocs; rel < relend; rel ++)
795
    {
796
      reloc_howto_type *           howto;
797
      unsigned long                r_symndx;
798
      Elf_Internal_Sym *           sym;
799
      asection *                   sec;
800
      struct elf_link_hash_entry * h;
801
      bfd_vma                      relocation;
802
      bfd_reloc_status_type        r;
803
      const char *                 name = NULL;
804
      int                          r_type;
805
 
806
      r_type = ELF32_R_TYPE (rel->r_info);
807
 
808
      if (   r_type == R_XSTORMY16_GNU_VTINHERIT
809
          || r_type == R_XSTORMY16_GNU_VTENTRY)
810
        continue;
811
 
812
      r_symndx = ELF32_R_SYM (rel->r_info);
813
      howto  = xstormy16_elf_howto_table + ELF32_R_TYPE (rel->r_info);
814
      h      = NULL;
815
      sym    = NULL;
816
      sec    = NULL;
817
 
818
      if (r_symndx < symtab_hdr->sh_info)
819
        {
820
          sym = local_syms + r_symndx;
821
          sec = local_sections [r_symndx];
822
          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
823
        }
824
      else
825
        {
826
          bfd_boolean unresolved_reloc, warned;
827
 
828
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
829
                                   r_symndx, symtab_hdr, sym_hashes,
830
                                   h, sec, relocation,
831
                                   unresolved_reloc, warned);
832
        }
833
 
834
      if (sec != NULL && elf_discarded_section (sec))
835
        {
836
          /* For relocs against symbols from removed linkonce sections,
837
             or sections discarded by a linker script, we just want the
838
             section contents zeroed.  Avoid any special processing.  */
839
          _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
840
          rel->r_info = 0;
841
          rel->r_addend = 0;
842
          continue;
843
        }
844
 
845
      if (info->relocatable)
846
        continue;
847
 
848
      if (h != NULL)
849
        name = h->root.root.string;
850
      else
851
        {
852
          name = (bfd_elf_string_from_elf_section
853
                  (input_bfd, symtab_hdr->sh_link, sym->st_name));
854
          if (name == NULL || *name == '\0')
855
            name = bfd_section_name (input_bfd, sec);
856
        }
857
 
858
      switch (ELF32_R_TYPE (rel->r_info))
859
        {
860
        case R_XSTORMY16_24:
861
          {
862
            bfd_vma reloc = relocation + rel->r_addend;
863
            unsigned int x;
864
 
865
            x = bfd_get_32 (input_bfd, contents + rel->r_offset);
866
            x &= 0x0000ff00;
867
            x |= reloc & 0xff;
868
            x |= (reloc << 8) & 0xffff0000;
869
            bfd_put_32 (input_bfd, x, contents + rel->r_offset);
870
 
871
            if (reloc & ~0xffffff)
872
              r = bfd_reloc_overflow;
873
            else
874
              r = bfd_reloc_ok;
875
            break;
876
          }
877
 
878
        case R_XSTORMY16_FPTR16:
879
          {
880
            bfd_vma *plt_offset;
881
 
882
            if (h != NULL)
883
              plt_offset = &h->plt.offset;
884
            else
885
              plt_offset = elf_local_got_offsets (input_bfd) + r_symndx;
886
 
887
            if (relocation <= 0xffff)
888
              {
889
                /* If the symbol is in range for a 16-bit address, we should
890
                   have deallocated the plt entry in relax_section.  */
891
                BFD_ASSERT (*plt_offset == (bfd_vma) -1);
892
              }
893
            else
894
              {
895
                /* If the symbol is out of range for a 16-bit address,
896
                   we must have allocated a plt entry.  */
897
                BFD_ASSERT (*plt_offset != (bfd_vma) -1);
898
 
899
                /* If this is the first time we've processed this symbol,
900
                   fill in the plt entry with the correct symbol address.  */
901
                if ((*plt_offset & 1) == 0)
902
                  {
903
                    unsigned int x;
904
 
905
                    x = 0x00000200;  /* jmpf */
906
                    x |= relocation & 0xff;
907
                    x |= (relocation << 8) & 0xffff0000;
908
                    bfd_put_32 (input_bfd, x, splt->contents + *plt_offset);
909
                    *plt_offset |= 1;
910
                  }
911
 
912
                relocation = (splt->output_section->vma
913
                              + splt->output_offset
914
                              + (*plt_offset & -2));
915
              }
916
            r = _bfd_final_link_relocate (howto, input_bfd, input_section,
917
                                          contents, rel->r_offset,
918
                                          relocation, 0);
919
            break;
920
          }
921
 
922
        default:
923
          r = _bfd_final_link_relocate (howto, input_bfd, input_section,
924
                                        contents, rel->r_offset,
925
                                        relocation, rel->r_addend);
926
          break;
927
        }
928
 
929
      if (r != bfd_reloc_ok)
930
        {
931
          const char * msg = NULL;
932
 
933
          switch (r)
934
            {
935
            case bfd_reloc_overflow:
936
              r = info->callbacks->reloc_overflow
937
                (info, (h ? &h->root : NULL), name, howto->name,
938
                 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
939
              break;
940
 
941
            case bfd_reloc_undefined:
942
              r = info->callbacks->undefined_symbol
943
                (info, name, input_bfd, input_section, rel->r_offset,
944
                 TRUE);
945
              break;
946
 
947
            case bfd_reloc_outofrange:
948
              msg = _("internal error: out of range error");
949
              break;
950
 
951
            case bfd_reloc_notsupported:
952
              msg = _("internal error: unsupported relocation error");
953
              break;
954
 
955
            case bfd_reloc_dangerous:
956
              msg = _("internal error: dangerous relocation");
957
              break;
958
 
959
            default:
960
              msg = _("internal error: unknown error");
961
              break;
962
            }
963
 
964
          if (msg)
965
            r = info->callbacks->warning
966
              (info, msg, name, input_bfd, input_section, rel->r_offset);
967
 
968
          if (! r)
969
            return FALSE;
970
        }
971
    }
972
 
973
  return TRUE;
974
}
975
 
976
/* This must exist if dynobj is ever set.  */
977
 
978
static bfd_boolean
979
xstormy16_elf_finish_dynamic_sections (bfd *abfd ATTRIBUTE_UNUSED,
980
                                       struct bfd_link_info *info)
981
{
982
  bfd *dynobj;
983
  asection *splt;
984
 
985
  /* As an extra sanity check, verify that all plt entries have
986
     been filled in.  */
987
 
988
  if ((dynobj = elf_hash_table (info)->dynobj) != NULL
989
      && (splt = bfd_get_section_by_name (dynobj, ".plt")) != NULL)
990
    {
991
      bfd_byte *contents = splt->contents;
992
      unsigned int i, size = splt->size;
993
 
994
      for (i = 0; i < size; i += 4)
995
        {
996
          unsigned int x = bfd_get_32 (dynobj, contents + i);
997
 
998
          BFD_ASSERT (x != 0);
999
        }
1000
    }
1001
 
1002
  return TRUE;
1003
}
1004
 
1005
/* Return the section that should be marked against GC for a given
1006
   relocation.  */
1007
 
1008
static asection *
1009
xstormy16_elf_gc_mark_hook (asection *sec,
1010
                            struct bfd_link_info *info,
1011
                            Elf_Internal_Rela *rel,
1012
                            struct elf_link_hash_entry *h,
1013
                            Elf_Internal_Sym *sym)
1014
{
1015
  if (h != NULL)
1016
    switch (ELF32_R_TYPE (rel->r_info))
1017
      {
1018
      case R_XSTORMY16_GNU_VTINHERIT:
1019
      case R_XSTORMY16_GNU_VTENTRY:
1020
        return NULL;
1021
      }
1022
 
1023
  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
1024
}
1025
 
1026
#define ELF_ARCH                bfd_arch_xstormy16
1027
#define ELF_MACHINE_CODE        EM_XSTORMY16
1028
#define ELF_MAXPAGESIZE         0x100
1029
 
1030
#define TARGET_LITTLE_SYM       bfd_elf32_xstormy16_vec
1031
#define TARGET_LITTLE_NAME      "elf32-xstormy16"
1032
 
1033
#define elf_info_to_howto_rel                   NULL
1034
#define elf_info_to_howto                       xstormy16_info_to_howto_rela
1035
#define elf_backend_relocate_section            xstormy16_elf_relocate_section
1036
#define elf_backend_gc_mark_hook                xstormy16_elf_gc_mark_hook
1037
#define elf_backend_check_relocs                xstormy16_elf_check_relocs
1038
#define elf_backend_always_size_sections \
1039
  xstormy16_elf_always_size_sections
1040
#define elf_backend_omit_section_dynsym \
1041
  ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
1042
#define elf_backend_finish_dynamic_sections \
1043
  xstormy16_elf_finish_dynamic_sections
1044
 
1045
#define elf_backend_can_gc_sections             1
1046
#define elf_backend_rela_normal                 1
1047
 
1048
#define bfd_elf32_bfd_reloc_type_lookup         xstormy16_reloc_type_lookup
1049
#define bfd_elf32_bfd_reloc_name_lookup \
1050
  xstormy16_reloc_name_lookup
1051
#define bfd_elf32_bfd_relax_section             xstormy16_elf_relax_section
1052
 
1053
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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