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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [bfd/] [elf32-xstormy16.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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