~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to binutils/bfd/elf32-fr30.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* FR30-specific support for 32-bit ELF.
 
2
   Copyright 1998, 1999, 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/fr30.h"
 
25
 
 
26
/* Forward declarations.  */
 
27
static bfd_reloc_status_type fr30_elf_i20_reloc
 
28
  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 
29
static bfd_reloc_status_type fr30_elf_i32_reloc
 
30
  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 
31
static reloc_howto_type * fr30_reloc_type_lookup
 
32
  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
 
33
static void fr30_info_to_howto_rela
 
34
  PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
 
35
static boolean fr30_elf_relocate_section
 
36
  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
 
37
           Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
 
38
static bfd_reloc_status_type fr30_final_link_relocate
 
39
  PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
 
40
           Elf_Internal_Rela *, bfd_vma));
 
41
static boolean fr30_elf_gc_sweep_hook
 
42
  PARAMS ((bfd *, struct bfd_link_info *, asection *,
 
43
           const Elf_Internal_Rela *));
 
44
static asection * fr30_elf_gc_mark_hook
 
45
  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 
46
           struct elf_link_hash_entry *, Elf_Internal_Sym *));
 
47
static boolean fr30_elf_check_relocs
 
48
  PARAMS ((bfd *, struct bfd_link_info *, asection *,
 
49
           const Elf_Internal_Rela *));
 
50
 
 
51
static reloc_howto_type fr30_elf_howto_table [] =
 
52
{
 
53
  /* This reloc does nothing.  */
 
54
  HOWTO (R_FR30_NONE,           /* type */
 
55
         0,                     /* rightshift */
 
56
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
 
57
         32,                    /* bitsize */
 
58
         false,                 /* pc_relative */
 
59
         0,                     /* bitpos */
 
60
         complain_overflow_bitfield, /* complain_on_overflow */
 
61
         bfd_elf_generic_reloc, /* special_function */
 
62
         "R_FR30_NONE",         /* name */
 
63
         false,                 /* partial_inplace */
 
64
         0,                     /* src_mask */
 
65
         0,                     /* dst_mask */
 
66
         false),                /* pcrel_offset */
 
67
 
 
68
  /* An 8 bit absolute relocation.  */
 
69
  HOWTO (R_FR30_8,              /* type */
 
70
         0,                     /* rightshift */
 
71
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
 
72
         8,                     /* bitsize */
 
73
         false,                 /* pc_relative */
 
74
         4,                     /* bitpos */
 
75
         complain_overflow_bitfield, /* complain_on_overflow */
 
76
         bfd_elf_generic_reloc, /* special_function */
 
77
         "R_FR30_8",            /* name */
 
78
         true,                  /* partial_inplace */
 
79
         0x0000,                /* src_mask */
 
80
         0x0ff0,                /* dst_mask */
 
81
         false),                /* pcrel_offset */
 
82
 
 
83
  /* A 20 bit absolute relocation.  */
 
84
  HOWTO (R_FR30_20,             /* type */
 
85
         0,                     /* rightshift */
 
86
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
 
87
         20,                    /* bitsize */
 
88
         false,                 /* pc_relative */
 
89
         0,                     /* bitpos */
 
90
         complain_overflow_bitfield, /* complain_on_overflow */
 
91
         fr30_elf_i20_reloc,    /* special_function */
 
92
         "R_FR30_20",           /* name */
 
93
         true,                  /* partial_inplace */
 
94
         0x00000000,            /* src_mask */
 
95
         0x00f0ffff,            /* dst_mask */
 
96
         false),                /* pcrel_offset */
 
97
 
 
98
  /* A 32 bit absolute relocation.  */
 
99
  HOWTO (R_FR30_32,             /* type */
 
100
         0,                     /* rightshift */
 
101
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
 
102
         32,                    /* bitsize */
 
103
         false,                 /* pc_relative */
 
104
         0,                     /* bitpos */
 
105
         complain_overflow_bitfield, /* complain_on_overflow */
 
106
         bfd_elf_generic_reloc, /* special_function */
 
107
         "R_FR30_32",           /* name */
 
108
         true,                  /* partial_inplace */
 
109
         0x00000000,            /* src_mask */
 
110
         0xffffffff,            /* dst_mask */
 
111
         false),                /* pcrel_offset */
 
112
 
 
113
  /* A 32 bit into 48 bits absolute relocation.  */
 
114
  HOWTO (R_FR30_48,             /* type */
 
115
         0,                     /* rightshift */
 
116
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
 
117
         32,                    /* bitsize */
 
118
         false,                 /* pc_relative */
 
119
         0,                     /* bitpos */
 
120
         complain_overflow_bitfield, /* complain_on_overflow */
 
121
         fr30_elf_i32_reloc,    /* special_function */
 
122
         "R_FR30_48",           /* name */
 
123
         true,                  /* partial_inplace */
 
124
         0x00000000,            /* src_mask */
 
125
         0xffffffff,            /* dst_mask */
 
126
         false),                /* pcrel_offset */
 
127
 
 
128
  /* A 6 bit absolute relocation.  */
 
129
  HOWTO (R_FR30_6_IN_4,         /* type */
 
130
         2,                     /* rightshift */
 
131
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
 
132
         6,                     /* bitsize */
 
133
         false,                 /* pc_relative */
 
134
         4,                     /* bitpos */
 
135
         complain_overflow_unsigned, /* complain_on_overflow */
 
136
         bfd_elf_generic_reloc, /* special_function */
 
137
         "R_FR30_6_IN_4",       /* name */
 
138
         true,                  /* partial_inplace */
 
139
         0x0000,                /* src_mask */
 
140
         0x00f0,                /* dst_mask */
 
141
         false),                /* pcrel_offset */
 
142
 
 
143
  /* An 8 bit absolute relocation.  */
 
144
  HOWTO (R_FR30_8_IN_8,         /* type */
 
145
         0,                     /* rightshift */
 
146
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
 
147
         8,                     /* bitsize */
 
148
         false,                 /* pc_relative */
 
149
         4,                     /* bitpos */
 
150
         complain_overflow_signed, /* complain_on_overflow */
 
151
         bfd_elf_generic_reloc,/* special_function */
 
152
         "R_FR30_8_IN_8",       /* name */
 
153
         true,                  /* partial_inplace */
 
154
         0x0000,                /* src_mask */
 
155
         0x0ff0,                /* dst_mask */
 
156
         false),                /* pcrel_offset */
 
157
 
 
158
  /* A 9 bit absolute relocation.  */
 
159
  HOWTO (R_FR30_9_IN_8,         /* type */
 
160
         1,                     /* rightshift */
 
161
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
 
162
         9,                     /* bitsize */
 
163
         false,                 /* pc_relative */
 
164
         4,                     /* bitpos */
 
165
         complain_overflow_signed, /* complain_on_overflow */
 
166
         bfd_elf_generic_reloc,/* special_function */
 
167
         "R_FR30_9_IN_8",       /* name */
 
168
         true,                  /* partial_inplace */
 
169
         0x0000,                /* src_mask */
 
170
         0x0ff0,                /* dst_mask */
 
171
         false),                /* pcrel_offset */
 
172
 
 
173
  /* A 10 bit absolute relocation.  */
 
174
  HOWTO (R_FR30_10_IN_8,        /* type */
 
175
         2,                     /* rightshift */
 
176
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
 
177
         10,                    /* bitsize */
 
178
         false,                 /* pc_relative */
 
179
         4,                     /* bitpos */
 
180
         complain_overflow_signed, /* complain_on_overflow */
 
181
         bfd_elf_generic_reloc,/* special_function */
 
182
         "R_FR30_10_IN_8",      /* name */
 
183
         true,                  /* partial_inplace */
 
184
         0x0000,                /* src_mask */
 
185
         0x0ff0,                /* dst_mask */
 
186
         false),                /* pcrel_offset */
 
187
 
 
188
  /* A PC relative 9 bit relocation, right shifted by 1.  */
 
189
  HOWTO (R_FR30_9_PCREL,        /* type */
 
190
         1,                     /* rightshift */
 
191
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
 
192
         9,                     /* bitsize */
 
193
         true,                  /* pc_relative */
 
194
         0,                     /* bitpos */
 
195
         complain_overflow_signed, /* complain_on_overflow */
 
196
         bfd_elf_generic_reloc, /* special_function */
 
197
         "R_FR30_9_PCREL",      /* name */
 
198
         false,                 /* partial_inplace */
 
199
         0x0000,                /* src_mask */
 
200
         0x00ff,                /* dst_mask */
 
201
         false),                /* pcrel_offset */
 
202
 
 
203
  /* A PC relative 12 bit relocation, right shifted by 1.  */
 
204
  HOWTO (R_FR30_12_PCREL,       /* type */
 
205
         1,                     /* rightshift */
 
206
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
 
207
         12,                    /* bitsize */
 
208
         true,                  /* pc_relative */
 
209
         0,                     /* bitpos */
 
210
         complain_overflow_signed, /* complain_on_overflow */
 
211
         bfd_elf_generic_reloc, /* special_function */
 
212
         "R_FR30_12_PCREL",     /* name */
 
213
         false,                 /* partial_inplace */
 
214
         0x0000,                /* src_mask */
 
215
         0x07ff,                /* dst_mask */
 
216
         false),                /* pcrel_offset */
 
217
  /* GNU extension to record C++ vtable hierarchy */
 
218
  HOWTO (R_FR30_GNU_VTINHERIT, /* type */
 
219
         0,                     /* rightshift */
 
220
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
 
221
         0,                     /* bitsize */
 
222
         false,                 /* pc_relative */
 
223
         0,                     /* bitpos */
 
224
         complain_overflow_dont, /* complain_on_overflow */
 
225
         NULL,                  /* special_function */
 
226
         "R_FR30_GNU_VTINHERIT", /* name */
 
227
         false,                 /* partial_inplace */
 
228
         0,                     /* src_mask */
 
229
         0,                     /* dst_mask */
 
230
         false),                /* pcrel_offset */
 
231
 
 
232
  /* GNU extension to record C++ vtable member usage */
 
233
  HOWTO (R_FR30_GNU_VTENTRY,     /* type */
 
234
         0,                     /* rightshift */
 
235
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
 
236
         0,                     /* bitsize */
 
237
         false,                 /* pc_relative */
 
238
         0,                     /* bitpos */
 
239
         complain_overflow_dont, /* complain_on_overflow */
 
240
         _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
 
241
         "R_FR30_GNU_VTENTRY",   /* name */
 
242
         false,                 /* partial_inplace */
 
243
         0,                     /* src_mask */
 
244
         0,                     /* dst_mask */
 
245
         false),                /* pcrel_offset */
 
246
};
 
247
 
 
248
/* Utility to actually perform an R_FR30_20 reloc.  */
 
249
 
 
250
static bfd_reloc_status_type
 
251
fr30_elf_i20_reloc (abfd, reloc_entry, symbol, data,
 
252
                    input_section, output_bfd, error_message)
 
253
     bfd *      abfd;
 
254
     arelent *  reloc_entry;
 
255
     asymbol *  symbol;
 
256
     PTR        data;
 
257
     asection * input_section;
 
258
     bfd *      output_bfd;
 
259
     char **    error_message ATTRIBUTE_UNUSED;
 
260
{
 
261
  bfd_vma       relocation;
 
262
  unsigned long x;
 
263
 
 
264
  /* This part is from bfd_elf_generic_reloc.  */
 
265
  if (output_bfd != (bfd *) NULL
 
266
      && (symbol->flags & BSF_SECTION_SYM) == 0
 
267
      && (! reloc_entry->howto->partial_inplace
 
268
          || reloc_entry->addend == 0))
 
269
    {
 
270
      reloc_entry->address += input_section->output_offset;
 
271
      return bfd_reloc_ok;
 
272
    }
 
273
 
 
274
  if (output_bfd != NULL)
 
275
    /* FIXME: See bfd_perform_relocation.  Is this right?  */
 
276
    return bfd_reloc_ok;
 
277
 
 
278
  relocation =
 
279
    symbol->value
 
280
    + symbol->section->output_section->vma
 
281
    + symbol->section->output_offset
 
282
    + reloc_entry->addend;
 
283
 
 
284
  if (relocation > (((bfd_vma) 1 << 20) - 1))
 
285
    return bfd_reloc_overflow;
 
286
 
 
287
  x = bfd_get_32 (abfd, (char *) data + reloc_entry->address);
 
288
  x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
 
289
  bfd_put_32 (abfd, (bfd_vma) x, (char *) data + reloc_entry->address);
 
290
 
 
291
  return bfd_reloc_ok;
 
292
}
 
293
 
 
294
/* Utility to actually perform a R_FR30_48 reloc.  */
 
295
 
 
296
static bfd_reloc_status_type
 
297
fr30_elf_i32_reloc (abfd, reloc_entry, symbol, data,
 
298
                    input_section, output_bfd, error_message)
 
299
     bfd *      abfd;
 
300
     arelent *  reloc_entry;
 
301
     asymbol *  symbol;
 
302
     PTR        data;
 
303
     asection * input_section;
 
304
     bfd *      output_bfd;
 
305
     char **    error_message ATTRIBUTE_UNUSED;
 
306
{
 
307
  bfd_vma       relocation;
 
308
 
 
309
  /* This part is from bfd_elf_generic_reloc.  */
 
310
  if (output_bfd != (bfd *) NULL
 
311
      && (symbol->flags & BSF_SECTION_SYM) == 0
 
312
      && (! reloc_entry->howto->partial_inplace
 
313
          || reloc_entry->addend == 0))
 
314
    {
 
315
      reloc_entry->address += input_section->output_offset;
 
316
      return bfd_reloc_ok;
 
317
    }
 
318
 
 
319
  if (output_bfd != NULL)
 
320
    /* FIXME: See bfd_perform_relocation.  Is this right?  */
 
321
    return bfd_reloc_ok;
 
322
 
 
323
  relocation =
 
324
    symbol->value
 
325
    + symbol->section->output_section->vma
 
326
    + symbol->section->output_offset
 
327
    + reloc_entry->addend;
 
328
 
 
329
  bfd_put_32 (abfd, relocation, (char *) data + reloc_entry->address + 2);
 
330
 
 
331
  return bfd_reloc_ok;
 
332
}
 
333
 
 
334
/* Map BFD reloc types to FR30 ELF reloc types.  */
 
335
 
 
336
struct fr30_reloc_map
 
337
{
 
338
  bfd_reloc_code_real_type bfd_reloc_val;
 
339
  unsigned int fr30_reloc_val;
 
340
};
 
341
 
 
342
static const struct fr30_reloc_map fr30_reloc_map [] =
 
343
{
 
344
  { BFD_RELOC_NONE,           R_FR30_NONE },
 
345
  { BFD_RELOC_8,              R_FR30_8 },
 
346
  { BFD_RELOC_FR30_20,        R_FR30_20 },
 
347
  { BFD_RELOC_32,             R_FR30_32 },
 
348
  { BFD_RELOC_FR30_48,        R_FR30_48 },
 
349
  { BFD_RELOC_FR30_6_IN_4,    R_FR30_6_IN_4 },
 
350
  { BFD_RELOC_FR30_8_IN_8,    R_FR30_8_IN_8 },
 
351
  { BFD_RELOC_FR30_9_IN_8,    R_FR30_9_IN_8 },
 
352
  { BFD_RELOC_FR30_10_IN_8,   R_FR30_10_IN_8 },
 
353
  { BFD_RELOC_FR30_9_PCREL,   R_FR30_9_PCREL },
 
354
  { BFD_RELOC_FR30_12_PCREL,  R_FR30_12_PCREL },
 
355
  { BFD_RELOC_VTABLE_INHERIT, R_FR30_GNU_VTINHERIT },
 
356
  { BFD_RELOC_VTABLE_ENTRY,   R_FR30_GNU_VTENTRY },
 
357
};
 
358
 
 
359
static reloc_howto_type *
 
360
fr30_reloc_type_lookup (abfd, code)
 
361
     bfd * abfd ATTRIBUTE_UNUSED;
 
362
     bfd_reloc_code_real_type code;
 
363
{
 
364
  unsigned int i;
 
365
 
 
366
  for (i = sizeof (fr30_reloc_map) / sizeof (fr30_reloc_map[0]);
 
367
       --i;)
 
368
    if (fr30_reloc_map [i].bfd_reloc_val == code)
 
369
      return & fr30_elf_howto_table [fr30_reloc_map[i].fr30_reloc_val];
 
370
 
 
371
  return NULL;
 
372
}
 
373
 
 
374
/* Set the howto pointer for an FR30 ELF reloc.  */
 
375
 
 
376
static void
 
377
fr30_info_to_howto_rela (abfd, cache_ptr, dst)
 
378
     bfd * abfd ATTRIBUTE_UNUSED;
 
379
     arelent * cache_ptr;
 
380
     Elf32_Internal_Rela * dst;
 
381
{
 
382
  unsigned int r_type;
 
383
 
 
384
  r_type = ELF32_R_TYPE (dst->r_info);
 
385
  BFD_ASSERT (r_type < (unsigned int) R_FR30_max);
 
386
  cache_ptr->howto = & fr30_elf_howto_table [r_type];
 
387
}
 
388
 
 
389
/* Perform a single relocation.  By default we use the standard BFD
 
390
   routines, but a few relocs, we have to do them ourselves.  */
 
391
 
 
392
static bfd_reloc_status_type
 
393
fr30_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation)
 
394
     reloc_howto_type *  howto;
 
395
     bfd *               input_bfd;
 
396
     asection *          input_section;
 
397
     bfd_byte *          contents;
 
398
     Elf_Internal_Rela * rel;
 
399
     bfd_vma             relocation;
 
400
{
 
401
  bfd_reloc_status_type r = bfd_reloc_ok;
 
402
  bfd_vma               x;
 
403
  bfd_signed_vma        srel;
 
404
 
 
405
  switch (howto->type)
 
406
    {
 
407
    case R_FR30_20:
 
408
      contents   += rel->r_offset;
 
409
      relocation += rel->r_addend;
 
410
 
 
411
      if (relocation > ((1 << 20) - 1))
 
412
        return bfd_reloc_overflow;
 
413
 
 
414
      x = bfd_get_32 (input_bfd, contents);
 
415
      x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
 
416
      bfd_put_32 (input_bfd, x, contents);
 
417
      break;
 
418
 
 
419
    case R_FR30_48:
 
420
      contents   += rel->r_offset + 2;
 
421
      relocation += rel->r_addend;
 
422
      bfd_put_32 (input_bfd, relocation, contents);
 
423
      break;
 
424
 
 
425
    case R_FR30_9_PCREL:
 
426
      contents   += rel->r_offset + 1;
 
427
      srel = (bfd_signed_vma) relocation;
 
428
      srel += rel->r_addend;
 
429
      srel -= rel->r_offset;
 
430
      srel -= 2;  /* Branch instructions add 2 to the PC...  */
 
431
      srel -= (input_section->output_section->vma +
 
432
                     input_section->output_offset);
 
433
 
 
434
      if (srel & 1)
 
435
        return bfd_reloc_outofrange;
 
436
      if (srel > ((1 << 8) - 1) || (srel < - (1 << 8)))
 
437
        return bfd_reloc_overflow;
 
438
 
 
439
      bfd_put_8 (input_bfd, srel >> 1, contents);
 
440
      break;
 
441
 
 
442
    case R_FR30_12_PCREL:
 
443
      contents   += rel->r_offset;
 
444
      srel = (bfd_signed_vma) relocation;
 
445
      srel += rel->r_addend;
 
446
      srel -= rel->r_offset;
 
447
      srel -= 2; /* Branch instructions add 2 to the PC...  */
 
448
      srel -= (input_section->output_section->vma +
 
449
                     input_section->output_offset);
 
450
 
 
451
      if (srel & 1)
 
452
        return bfd_reloc_outofrange;
 
453
      if (srel > ((1 << 11) - 1) || (srel < - (1 << 11)))
 
454
          return bfd_reloc_overflow;
 
455
 
 
456
      x = bfd_get_16 (input_bfd, contents);
 
457
      x = (x & 0xf800) | ((srel >> 1) & 0x7ff);
 
458
      bfd_put_16 (input_bfd, x, contents);
 
459
      break;
 
460
 
 
461
    default:
 
462
      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
 
463
                                    contents, rel->r_offset,
 
464
                                    relocation, rel->r_addend);
 
465
    }
 
466
 
 
467
  return r;
 
468
}
 
469
 
 
470
/* Relocate an FR30 ELF section.
 
471
   There is some attempt to make this function usable for many architectures,
 
472
   both USE_REL and USE_RELA ['twould be nice if such a critter existed],
 
473
   if only to serve as a learning tool.
 
474
 
 
475
   The RELOCATE_SECTION function is called by the new ELF backend linker
 
476
   to handle the relocations for a section.
 
477
 
 
478
   The relocs are always passed as Rela structures; if the section
 
479
   actually uses Rel structures, the r_addend field will always be
 
480
   zero.
 
481
 
 
482
   This function is responsible for adjusting the section contents as
 
483
   necessary, and (if using Rela relocs and generating a relocateable
 
484
   output file) adjusting the reloc addend as necessary.
 
485
 
 
486
   This function does not have to worry about setting the reloc
 
487
   address or the reloc symbol index.
 
488
 
 
489
   LOCAL_SYMS is a pointer to the swapped in local symbols.
 
490
 
 
491
   LOCAL_SECTIONS is an array giving the section in the input file
 
492
   corresponding to the st_shndx field of each local symbol.
 
493
 
 
494
   The global hash table entry for the global symbols can be found
 
495
   via elf_sym_hashes (input_bfd).
 
496
 
 
497
   When generating relocateable output, this function must handle
 
498
   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
 
499
   going to be the section symbol corresponding to the output
 
500
   section, which means that the addend must be adjusted
 
501
   accordingly.  */
 
502
 
 
503
static boolean
 
504
fr30_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
505
                           contents, relocs, local_syms, local_sections)
 
506
     bfd *                   output_bfd;
 
507
     struct bfd_link_info *  info;
 
508
     bfd *                   input_bfd;
 
509
     asection *              input_section;
 
510
     bfd_byte *              contents;
 
511
     Elf_Internal_Rela *     relocs;
 
512
     Elf_Internal_Sym *      local_syms;
 
513
     asection **             local_sections;
 
514
{
 
515
  Elf_Internal_Shdr *           symtab_hdr;
 
516
  struct elf_link_hash_entry ** sym_hashes;
 
517
  Elf_Internal_Rela *           rel;
 
518
  Elf_Internal_Rela *           relend;
 
519
 
 
520
  if (info->relocateable)
 
521
    return true;
 
522
 
 
523
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
 
524
  sym_hashes = elf_sym_hashes (input_bfd);
 
525
  relend     = relocs + input_section->reloc_count;
 
526
 
 
527
  for (rel = relocs; rel < relend; rel ++)
 
528
    {
 
529
      reloc_howto_type *           howto;
 
530
      unsigned long                r_symndx;
 
531
      Elf_Internal_Sym *           sym;
 
532
      asection *                   sec;
 
533
      struct elf_link_hash_entry * h;
 
534
      bfd_vma                      relocation;
 
535
      bfd_reloc_status_type        r;
 
536
      const char *                 name = NULL;
 
537
      int                          r_type;
 
538
 
 
539
      r_type = ELF32_R_TYPE (rel->r_info);
 
540
 
 
541
      if (   r_type == R_FR30_GNU_VTINHERIT
 
542
          || r_type == R_FR30_GNU_VTENTRY)
 
543
        continue;
 
544
 
 
545
      r_symndx = ELF32_R_SYM (rel->r_info);
 
546
 
 
547
      howto  = fr30_elf_howto_table + ELF32_R_TYPE (rel->r_info);
 
548
      h      = NULL;
 
549
      sym    = NULL;
 
550
      sec    = NULL;
 
551
 
 
552
      if (r_symndx < symtab_hdr->sh_info)
 
553
        {
 
554
          sym = local_syms + r_symndx;
 
555
          sec = local_sections [r_symndx];
 
556
          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
 
557
 
 
558
          name = bfd_elf_string_from_elf_section
 
559
            (input_bfd, symtab_hdr->sh_link, sym->st_name);
 
560
          name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
 
561
#if 0
 
562
          fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
 
563
                   sec->name, name, sym->st_name,
 
564
                   sec->output_section->vma, sec->output_offset,
 
565
                   sym->st_value, rel->r_addend);
 
566
#endif
 
567
        }
 
568
      else
 
569
        {
 
570
          h = sym_hashes [r_symndx - symtab_hdr->sh_info];
 
571
 
 
572
          while (h->root.type == bfd_link_hash_indirect
 
573
                 || h->root.type == bfd_link_hash_warning)
 
574
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
575
 
 
576
          name = h->root.root.string;
 
577
 
 
578
          if (h->root.type == bfd_link_hash_defined
 
579
              || h->root.type == bfd_link_hash_defweak)
 
580
            {
 
581
              sec = h->root.u.def.section;
 
582
              relocation = (h->root.u.def.value
 
583
                            + sec->output_section->vma
 
584
                            + sec->output_offset);
 
585
#if 0
 
586
              fprintf (stderr,
 
587
                       "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n",
 
588
                       sec->name, name, h->root.u.def.value,
 
589
                       sec->output_section->vma, sec->output_offset, relocation);
 
590
#endif
 
591
            }
 
592
          else if (h->root.type == bfd_link_hash_undefweak)
 
593
            {
 
594
#if 0
 
595
              fprintf (stderr, "undefined: sec: %s, name: %s\n",
 
596
                       sec->name, name);
 
597
#endif
 
598
              relocation = 0;
 
599
            }
 
600
          else
 
601
            {
 
602
              if (! ((*info->callbacks->undefined_symbol)
 
603
                     (info, h->root.root.string, input_bfd,
 
604
                      input_section, rel->r_offset, true)))
 
605
                return false;
 
606
#if 0
 
607
              fprintf (stderr, "unknown: name: %s\n", name);
 
608
#endif
 
609
              relocation = 0;
 
610
            }
 
611
        }
 
612
 
 
613
      r = fr30_final_link_relocate (howto, input_bfd, input_section,
 
614
                                     contents, rel, relocation);
 
615
 
 
616
      if (r != bfd_reloc_ok)
 
617
        {
 
618
          const char * msg = (const char *) NULL;
 
619
 
 
620
          switch (r)
 
621
            {
 
622
            case bfd_reloc_overflow:
 
623
              r = info->callbacks->reloc_overflow
 
624
                (info, name, howto->name, (bfd_vma) 0,
 
625
                 input_bfd, input_section, rel->r_offset);
 
626
              break;
 
627
 
 
628
            case bfd_reloc_undefined:
 
629
              r = info->callbacks->undefined_symbol
 
630
                (info, name, input_bfd, input_section, rel->r_offset,
 
631
                 true);
 
632
              break;
 
633
 
 
634
            case bfd_reloc_outofrange:
 
635
              msg = _("internal error: out of range error");
 
636
              break;
 
637
 
 
638
            case bfd_reloc_notsupported:
 
639
              msg = _("internal error: unsupported relocation error");
 
640
              break;
 
641
 
 
642
            case bfd_reloc_dangerous:
 
643
              msg = _("internal error: dangerous relocation");
 
644
              break;
 
645
 
 
646
            default:
 
647
              msg = _("internal error: unknown error");
 
648
              break;
 
649
            }
 
650
 
 
651
          if (msg)
 
652
            r = info->callbacks->warning
 
653
              (info, msg, name, input_bfd, input_section, rel->r_offset);
 
654
 
 
655
          if (! r)
 
656
            return false;
 
657
        }
 
658
    }
 
659
 
 
660
  return true;
 
661
}
 
662
 
 
663
/* Return the section that should be marked against GC for a given
 
664
   relocation.  */
 
665
 
 
666
static asection *
 
667
fr30_elf_gc_mark_hook (sec, info, rel, h, sym)
 
668
     asection *                   sec;
 
669
     struct bfd_link_info *       info ATTRIBUTE_UNUSED;
 
670
     Elf_Internal_Rela *          rel;
 
671
     struct elf_link_hash_entry * h;
 
672
     Elf_Internal_Sym *           sym;
 
673
{
 
674
  if (h != NULL)
 
675
    {
 
676
      switch (ELF32_R_TYPE (rel->r_info))
 
677
        {
 
678
        case R_FR30_GNU_VTINHERIT:
 
679
        case R_FR30_GNU_VTENTRY:
 
680
          break;
 
681
 
 
682
        default:
 
683
          switch (h->root.type)
 
684
            {
 
685
            case bfd_link_hash_defined:
 
686
            case bfd_link_hash_defweak:
 
687
              return h->root.u.def.section;
 
688
 
 
689
            case bfd_link_hash_common:
 
690
              return h->root.u.c.p->section;
 
691
 
 
692
            default:
 
693
              break;
 
694
            }
 
695
        }
 
696
    }
 
697
  else
 
698
    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 
699
 
 
700
  return NULL;
 
701
}
 
702
 
 
703
/* Update the got entry reference counts for the section being removed.  */
 
704
 
 
705
static boolean
 
706
fr30_elf_gc_sweep_hook (abfd, info, sec, relocs)
 
707
     bfd *                     abfd ATTRIBUTE_UNUSED;
 
708
     struct bfd_link_info *    info ATTRIBUTE_UNUSED;
 
709
     asection *                sec ATTRIBUTE_UNUSED;
 
710
     const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED;
 
711
{
 
712
  return true;
 
713
}
 
714
 
 
715
/* Look through the relocs for a section during the first phase.
 
716
   Since we don't do .gots or .plts, we just need to consider the
 
717
   virtual table relocs for gc.  */
 
718
 
 
719
static boolean
 
720
fr30_elf_check_relocs (abfd, info, sec, relocs)
 
721
     bfd *abfd;
 
722
     struct bfd_link_info *info;
 
723
     asection *sec;
 
724
     const Elf_Internal_Rela *relocs;
 
725
{
 
726
  Elf_Internal_Shdr *symtab_hdr;
 
727
  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
 
728
  const Elf_Internal_Rela *rel;
 
729
  const Elf_Internal_Rela *rel_end;
 
730
 
 
731
  if (info->relocateable)
 
732
    return true;
 
733
 
 
734
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
 
735
  sym_hashes = elf_sym_hashes (abfd);
 
736
  sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
 
737
  if (!elf_bad_symtab (abfd))
 
738
    sym_hashes_end -= symtab_hdr->sh_info;
 
739
 
 
740
  rel_end = relocs + sec->reloc_count;
 
741
  for (rel = relocs; rel < rel_end; rel++)
 
742
    {
 
743
      struct elf_link_hash_entry *h;
 
744
      unsigned long r_symndx;
 
745
 
 
746
      r_symndx = ELF32_R_SYM (rel->r_info);
 
747
      if (r_symndx < symtab_hdr->sh_info)
 
748
        h = NULL;
 
749
      else
 
750
        h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 
751
 
 
752
      switch (ELF32_R_TYPE (rel->r_info))
 
753
        {
 
754
        /* This relocation describes the C++ object vtable hierarchy.
 
755
           Reconstruct it for later use during GC.  */
 
756
        case R_FR30_GNU_VTINHERIT:
 
757
          if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
 
758
            return false;
 
759
          break;
 
760
 
 
761
        /* This relocation describes which C++ vtable entries are actually
 
762
           used.  Record for later use during GC.  */
 
763
        case R_FR30_GNU_VTENTRY:
 
764
          if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
 
765
            return false;
 
766
          break;
 
767
        }
 
768
    }
 
769
 
 
770
  return true;
 
771
}
 
772
 
 
773
#define ELF_ARCH                bfd_arch_fr30
 
774
#define ELF_MACHINE_CODE        EM_FR30
 
775
#define ELF_MACHINE_ALT1        EM_CYGNUS_FR30
 
776
#define ELF_MAXPAGESIZE         0x1000
 
777
 
 
778
#define TARGET_BIG_SYM          bfd_elf32_fr30_vec
 
779
#define TARGET_BIG_NAME         "elf32-fr30"
 
780
 
 
781
#define elf_info_to_howto_rel                   NULL
 
782
#define elf_info_to_howto                       fr30_info_to_howto_rela
 
783
#define elf_backend_relocate_section            fr30_elf_relocate_section
 
784
#define elf_backend_gc_mark_hook                fr30_elf_gc_mark_hook
 
785
#define elf_backend_gc_sweep_hook               fr30_elf_gc_sweep_hook
 
786
#define elf_backend_check_relocs                fr30_elf_check_relocs
 
787
 
 
788
#define elf_backend_can_gc_sections             1
 
789
#define elf_backend_rela_normal                 1
 
790
 
 
791
#define bfd_elf32_bfd_reloc_type_lookup         fr30_reloc_type_lookup
 
792
 
 
793
#include "elf32-target.h"