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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [bfd/] [elf32-crx.c] - Blame information for rev 298

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

Line No. Rev Author Line
1 24 jeremybenn
/* BFD back-end for National Semiconductor's CRX ELF
2 225 jeremybenn
   Copyright 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
3 24 jeremybenn
   Written by Tomer Levi, NSC, Israel.
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 "bfdlink.h"
25
#include "libbfd.h"
26
#include "elf-bfd.h"
27
#include "elf/crx.h"
28
 
29
static reloc_howto_type *elf_crx_reloc_type_lookup
30
  (bfd *, bfd_reloc_code_real_type);
31
static void elf_crx_info_to_howto
32
  (bfd *, arelent *, Elf_Internal_Rela *);
33
static bfd_boolean elf32_crx_relax_delete_bytes
34
  (struct bfd_link_info *, bfd *, asection *, bfd_vma, int);
35
static bfd_reloc_status_type crx_elf_final_link_relocate
36
  (reloc_howto_type *, bfd *, bfd *, asection *,
37
   bfd_byte *, bfd_vma, bfd_vma, bfd_vma,
38
   struct bfd_link_info *, asection *, int);
39
static bfd_boolean elf32_crx_relocate_section
40
  (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
41
   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
42
static bfd_boolean elf32_crx_relax_section
43
  (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
44
static bfd_byte * elf32_crx_get_relocated_section_contents
45
  (bfd *, struct bfd_link_info *, struct bfd_link_order *,
46
   bfd_byte *, bfd_boolean, asymbol **);
47
 
48
/* crx_reloc_map array maps BFD relocation enum into a CRGAS relocation type.  */
49
 
50
struct crx_reloc_map
51
{
52
  bfd_reloc_code_real_type bfd_reloc_enum; /* BFD relocation enum.  */
53
  unsigned short crx_reloc_type;           /* CRX relocation type.  */
54
};
55
 
56
static const struct crx_reloc_map crx_reloc_map[R_CRX_MAX] =
57
{
58
  {BFD_RELOC_NONE,          R_CRX_NONE},
59
  {BFD_RELOC_CRX_REL4,      R_CRX_REL4},
60
  {BFD_RELOC_CRX_REL8,      R_CRX_REL8},
61
  {BFD_RELOC_CRX_REL8_CMP,  R_CRX_REL8_CMP},
62
  {BFD_RELOC_CRX_REL16,     R_CRX_REL16},
63
  {BFD_RELOC_CRX_REL24,     R_CRX_REL24},
64
  {BFD_RELOC_CRX_REL32,     R_CRX_REL32},
65
  {BFD_RELOC_CRX_REGREL12,  R_CRX_REGREL12},
66
  {BFD_RELOC_CRX_REGREL22,  R_CRX_REGREL22},
67
  {BFD_RELOC_CRX_REGREL28,  R_CRX_REGREL28},
68
  {BFD_RELOC_CRX_REGREL32,  R_CRX_REGREL32},
69
  {BFD_RELOC_CRX_ABS16,     R_CRX_ABS16},
70
  {BFD_RELOC_CRX_ABS32,     R_CRX_ABS32},
71
  {BFD_RELOC_CRX_NUM8,      R_CRX_NUM8},
72
  {BFD_RELOC_CRX_NUM16,     R_CRX_NUM16},
73
  {BFD_RELOC_CRX_NUM32,     R_CRX_NUM32},
74
  {BFD_RELOC_CRX_IMM16,     R_CRX_IMM16},
75
  {BFD_RELOC_CRX_IMM32,     R_CRX_IMM32},
76
  {BFD_RELOC_CRX_SWITCH8,   R_CRX_SWITCH8},
77
  {BFD_RELOC_CRX_SWITCH16,  R_CRX_SWITCH16},
78
  {BFD_RELOC_CRX_SWITCH32,  R_CRX_SWITCH32}
79
};
80
 
81
static reloc_howto_type crx_elf_howto_table[] =
82
{
83
  HOWTO (R_CRX_NONE,            /* type */
84
         0,                      /* rightshift */
85
         2,                     /* size */
86
         32,                    /* bitsize */
87
         FALSE,                 /* pc_relative */
88
         0,                      /* bitpos */
89
         complain_overflow_dont,/* complain_on_overflow */
90
         bfd_elf_generic_reloc, /* special_function */
91
         "R_CRX_NONE",          /* name */
92
         FALSE,                 /* partial_inplace */
93
         0,                      /* src_mask */
94
         0,                      /* dst_mask */
95
         FALSE),                /* pcrel_offset */
96
 
97
  HOWTO (R_CRX_REL4,            /* type */
98
         1,                     /* rightshift */
99
         0,                      /* size */
100
         4,                     /* bitsize */
101
         TRUE,                  /* pc_relative */
102
         0,                      /* bitpos */
103
         complain_overflow_bitfield,/* complain_on_overflow */
104
         bfd_elf_generic_reloc, /* special_function */
105
         "R_CRX_REL4",          /* name */
106
         FALSE,                 /* partial_inplace */
107 225 jeremybenn
         0x0,                   /* src_mask */
108 24 jeremybenn
         0xf,                   /* dst_mask */
109
         FALSE),                /* pcrel_offset */
110
 
111
  HOWTO (R_CRX_REL8,            /* type */
112
         1,                     /* rightshift */
113
         0,                      /* size */
114
         8,                     /* bitsize */
115
         TRUE,                  /* pc_relative */
116
         0,                      /* bitpos */
117
         complain_overflow_bitfield,/* complain_on_overflow */
118
         bfd_elf_generic_reloc, /* special_function */
119
         "R_CRX_REL8",          /* name */
120
         FALSE,                 /* partial_inplace */
121 225 jeremybenn
         0x0,                   /* src_mask */
122 24 jeremybenn
         0xff,                  /* dst_mask */
123
         FALSE),                /* pcrel_offset */
124
 
125
  HOWTO (R_CRX_REL8_CMP,        /* type */
126
         1,                     /* rightshift */
127
         0,                      /* size */
128
         8,                     /* bitsize */
129
         TRUE,                  /* pc_relative */
130
         0,                      /* bitpos */
131
         complain_overflow_bitfield,/* complain_on_overflow */
132
         bfd_elf_generic_reloc, /* special_function */
133
         "R_CRX_REL8_CMP",      /* name */
134
         FALSE,                 /* partial_inplace */
135 225 jeremybenn
         0x0,                   /* src_mask */
136 24 jeremybenn
         0xff,                  /* dst_mask */
137
         FALSE),                /* pcrel_offset */
138
 
139
  HOWTO (R_CRX_REL16,           /* type */
140
         1,                     /* rightshift */
141
         1,                     /* size */
142
         16,                    /* bitsize */
143
         TRUE,                  /* pc_relative */
144
         0,                      /* bitpos */
145
         complain_overflow_bitfield,/* complain_on_overflow */
146
         bfd_elf_generic_reloc, /* special_function */
147
         "R_CRX_REL16",         /* name */
148
         FALSE,                 /* partial_inplace */
149 225 jeremybenn
         0x0,                   /* src_mask */
150 24 jeremybenn
         0xffff,                /* dst_mask */
151
         FALSE),                /* pcrel_offset */
152
 
153
  HOWTO (R_CRX_REL24,           /* type */
154
         1,                     /* rightshift */
155
         2,                     /* size */
156
         24,                    /* bitsize */
157
         TRUE,                  /* pc_relative */
158
         0,                      /* bitpos */
159
         complain_overflow_bitfield,/* complain_on_overflow */
160
         bfd_elf_generic_reloc, /* special_function */
161
         "R_CRX_REL24",         /* name */
162
         FALSE,                 /* partial_inplace */
163 225 jeremybenn
         0x0,                   /* src_mask */
164 24 jeremybenn
         0xffffff,              /* dst_mask */
165
         FALSE),                /* pcrel_offset */
166
 
167
  HOWTO (R_CRX_REL32,           /* type */
168
         1,                     /* rightshift */
169
         2,                     /* size */
170
         32,                    /* bitsize */
171
         TRUE,                  /* pc_relative */
172
         0,                      /* bitpos */
173
         complain_overflow_bitfield,/* complain_on_overflow */
174
         bfd_elf_generic_reloc, /* special_function */
175
         "R_CRX_REL32",         /* name */
176
         FALSE,                 /* partial_inplace */
177 225 jeremybenn
         0x0,                   /* src_mask */
178 24 jeremybenn
         0xffffffff,            /* dst_mask */
179
         FALSE),                /* pcrel_offset */
180
 
181
  HOWTO (R_CRX_REGREL12,        /* type */
182
         0,                      /* rightshift */
183
         1,                     /* size */
184
         12,                    /* bitsize */
185
         FALSE,                 /* pc_relative */
186
         0,                      /* bitpos */
187
         complain_overflow_bitfield,/* complain_on_overflow */
188
         bfd_elf_generic_reloc, /* special_function */
189
         "R_CRX_REGREL12",      /* name */
190
         FALSE,                 /* partial_inplace */
191 225 jeremybenn
         0x0,                   /* src_mask */
192 24 jeremybenn
         0xfff,                 /* dst_mask */
193
         FALSE),                /* pcrel_offset */
194
 
195
  HOWTO (R_CRX_REGREL22,        /* type */
196
         0,                      /* rightshift */
197
         2,                     /* size */
198
         22,                    /* bitsize */
199
         FALSE,                 /* pc_relative */
200
         0,                      /* bitpos */
201
         complain_overflow_bitfield,/* complain_on_overflow */
202
         bfd_elf_generic_reloc, /* special_function */
203
         "R_CRX_REGREL22",      /* name */
204
         FALSE,                 /* partial_inplace */
205 225 jeremybenn
         0x0,                   /* src_mask */
206 24 jeremybenn
         0x3fffff,              /* dst_mask */
207
         FALSE),                /* pcrel_offset */
208
 
209
  HOWTO (R_CRX_REGREL28,        /* type */
210
         0,                      /* rightshift */
211
         2,                     /* size */
212
         28,                    /* bitsize */
213
         FALSE,                 /* pc_relative */
214
         0,                      /* bitpos */
215
         complain_overflow_bitfield,/* complain_on_overflow */
216
         bfd_elf_generic_reloc, /* special_function */
217
         "R_CRX_REGREL28",      /* name */
218
         FALSE,                 /* partial_inplace */
219 225 jeremybenn
         0x0,                   /* src_mask */
220 24 jeremybenn
         0xfffffff,             /* dst_mask */
221
         FALSE),                /* pcrel_offset */
222
 
223
  HOWTO (R_CRX_REGREL32,        /* type */
224
         0,                      /* rightshift */
225
         2,                     /* size */
226
         32,                    /* bitsize */
227
         FALSE,                 /* pc_relative */
228
         0,                      /* bitpos */
229
         complain_overflow_bitfield,/* complain_on_overflow */
230
         bfd_elf_generic_reloc, /* special_function */
231
         "R_CRX_REGREL32",      /* name */
232
         FALSE,                 /* partial_inplace */
233 225 jeremybenn
         0x0,                   /* src_mask */
234 24 jeremybenn
         0xffffffff,            /* dst_mask */
235
         FALSE),                /* pcrel_offset */
236
 
237
  HOWTO (R_CRX_ABS16,           /* type */
238
         0,                      /* rightshift */
239
         1,                     /* size */
240
         16,                    /* bitsize */
241
         FALSE,                 /* pc_relative */
242
         0,                      /* bitpos */
243
         complain_overflow_bitfield,/* complain_on_overflow */
244
         bfd_elf_generic_reloc, /* special_function */
245
         "R_CRX_ABS16",         /* name */
246
         FALSE,                 /* partial_inplace */
247 225 jeremybenn
         0x0,                   /* src_mask */
248 24 jeremybenn
         0xffff,                /* dst_mask */
249
         FALSE),                /* pcrel_offset */
250
 
251
  HOWTO (R_CRX_ABS32,           /* type */
252
         0,                      /* rightshift */
253
         2,                     /* size */
254
         32,                    /* bitsize */
255
         FALSE,                 /* pc_relative */
256
         0,                      /* bitpos */
257
         complain_overflow_bitfield,/* complain_on_overflow */
258
         bfd_elf_generic_reloc, /* special_function */
259
         "R_CRX_ABS32",         /* name */
260
         FALSE,                 /* partial_inplace */
261 225 jeremybenn
         0x0,                   /* src_mask */
262 24 jeremybenn
         0xffffffff,            /* dst_mask */
263
         FALSE),                /* pcrel_offset */
264
 
265
  HOWTO (R_CRX_NUM8,            /* type */
266
         0,                      /* rightshift */
267
         0,                      /* size */
268
         8,                     /* bitsize */
269
         FALSE,                 /* pc_relative */
270
         0,                      /* bitpos */
271
         complain_overflow_bitfield,/* complain_on_overflow */
272
         bfd_elf_generic_reloc, /* special_function */
273
         "R_CRX_NUM8",          /* name */
274
         FALSE,                 /* partial_inplace */
275 225 jeremybenn
         0x0,                   /* src_mask */
276 24 jeremybenn
         0xff,                  /* dst_mask */
277
         FALSE),                /* pcrel_offset */
278
 
279
  HOWTO (R_CRX_NUM16,           /* type */
280
         0,                      /* rightshift */
281
         1,                     /* size */
282
         16,                    /* bitsize */
283
         FALSE,                 /* pc_relative */
284
         0,                      /* bitpos */
285
         complain_overflow_bitfield,/* complain_on_overflow */
286
         bfd_elf_generic_reloc, /* special_function */
287
         "R_CRX_NUM16",         /* name */
288
         FALSE,                 /* partial_inplace */
289 225 jeremybenn
         0x0,                   /* src_mask */
290 24 jeremybenn
         0xffff,                /* dst_mask */
291
         FALSE),                /* pcrel_offset */
292
 
293
  HOWTO (R_CRX_NUM32,           /* type */
294
         0,                      /* rightshift */
295
         2,                     /* size */
296
         32,                    /* bitsize */
297
         FALSE,                 /* pc_relative */
298
         0,                      /* bitpos */
299
         complain_overflow_bitfield,/* complain_on_overflow */
300
         bfd_elf_generic_reloc, /* special_function */
301
         "R_CRX_NUM32",         /* name */
302
         FALSE,                 /* partial_inplace */
303 225 jeremybenn
         0x0,                   /* src_mask */
304 24 jeremybenn
         0xffffffff,            /* dst_mask */
305
         FALSE),                /* pcrel_offset */
306
 
307
  HOWTO (R_CRX_IMM16,           /* type */
308
         0,                      /* rightshift */
309
         1,                     /* size */
310
         16,                    /* bitsize */
311
         FALSE,                 /* pc_relative */
312
         0,                      /* bitpos */
313
         complain_overflow_bitfield,/* complain_on_overflow */
314
         bfd_elf_generic_reloc, /* special_function */
315
         "R_CRX_IMM16",         /* name */
316
         FALSE,                 /* partial_inplace */
317 225 jeremybenn
         0x0,                   /* src_mask */
318 24 jeremybenn
         0xffff,                /* dst_mask */
319
         FALSE),                /* pcrel_offset */
320
 
321
  HOWTO (R_CRX_IMM32,           /* type */
322
         0,                      /* rightshift */
323
         2,                     /* size */
324
         32,                    /* bitsize */
325
         FALSE,                 /* pc_relative */
326
         0,                      /* bitpos */
327
         complain_overflow_bitfield,/* complain_on_overflow */
328
         bfd_elf_generic_reloc, /* special_function */
329
         "R_CRX_IMM32",         /* name */
330
         FALSE,                 /* partial_inplace */
331 225 jeremybenn
         0x0,                   /* src_mask */
332 24 jeremybenn
         0xffffffff,            /* dst_mask */
333
         FALSE),                /* pcrel_offset */
334
 
335
  /* An 8 bit switch table entry.  This is generated for an expression
336
     such as ``.byte L1 - L2''.  The offset holds the difference
337
     between the reloc address and L2.  */
338
  HOWTO (R_CRX_SWITCH8,         /* type */
339
         0,                      /* rightshift */
340
         0,                      /* size (0 = byte, 1 = short, 2 = long) */
341
         8,                     /* bitsize */
342
         FALSE,                 /* pc_relative */
343
         0,                      /* bitpos */
344
         complain_overflow_unsigned, /* complain_on_overflow */
345
         bfd_elf_generic_reloc, /* special_function */
346
         "R_CRX_SWITCH8",       /* name */
347
         FALSE,                 /* partial_inplace */
348 225 jeremybenn
         0x0,                   /* src_mask */
349 24 jeremybenn
         0xff,                  /* dst_mask */
350
         TRUE),                 /* pcrel_offset */
351
 
352
  /* A 16 bit switch table entry.  This is generated for an expression
353
     such as ``.word L1 - L2''.  The offset holds the difference
354
     between the reloc address and L2.  */
355
  HOWTO (R_CRX_SWITCH16,        /* type */
356
         0,                      /* rightshift */
357
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
358
         16,                    /* bitsize */
359
         FALSE,                 /* pc_relative */
360
         0,                      /* bitpos */
361
         complain_overflow_unsigned, /* complain_on_overflow */
362
         bfd_elf_generic_reloc, /* special_function */
363
         "R_CRX_SWITCH16",      /* name */
364
         FALSE,                 /* partial_inplace */
365 225 jeremybenn
         0x0,                   /* src_mask */
366 24 jeremybenn
         0xffff,                /* dst_mask */
367
         TRUE),                 /* pcrel_offset */
368
 
369
  /* A 32 bit switch table entry.  This is generated for an expression
370
     such as ``.long L1 - L2''.  The offset holds the difference
371
     between the reloc address and L2.  */
372
  HOWTO (R_CRX_SWITCH32,        /* type */
373
         0,                      /* rightshift */
374
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
375
         32,                    /* bitsize */
376
         FALSE,                 /* pc_relative */
377
         0,                      /* bitpos */
378
         complain_overflow_unsigned, /* complain_on_overflow */
379
         bfd_elf_generic_reloc, /* special_function */
380
         "R_CRX_SWITCH32",      /* name */
381
         FALSE,                 /* partial_inplace */
382 225 jeremybenn
         0x0,                   /* src_mask */
383 24 jeremybenn
         0xffffffff,            /* dst_mask */
384
         TRUE)                  /* pcrel_offset */
385
};
386
 
387
/* Retrieve a howto ptr using a BFD reloc_code.  */
388
 
389
static reloc_howto_type *
390
elf_crx_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
391
                           bfd_reloc_code_real_type code)
392
{
393
  unsigned int i;
394
 
395
  for (i = 0; i < R_CRX_MAX; i++)
396
    if (code == crx_reloc_map[i].bfd_reloc_enum)
397
      return &crx_elf_howto_table[crx_reloc_map[i].crx_reloc_type];
398
 
399
  printf ("This relocation Type is not supported -0x%x\n", code);
400
  return 0;
401
}
402
 
403
static reloc_howto_type *
404
elf_crx_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
405
                           const char *r_name)
406
{
407
  unsigned int i;
408
 
409
  for (i = 0;
410
       i < sizeof (crx_elf_howto_table) / sizeof (crx_elf_howto_table[0]);
411
       i++)
412
    if (crx_elf_howto_table[i].name != NULL
413
        && strcasecmp (crx_elf_howto_table[i].name, r_name) == 0)
414
      return &crx_elf_howto_table[i];
415
 
416
  return NULL;
417
}
418
 
419
/* Retrieve a howto ptr using an internal relocation entry.  */
420
 
421
static void
422
elf_crx_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
423
                       Elf_Internal_Rela *dst)
424
{
425
  unsigned int r_type = ELF32_R_TYPE (dst->r_info);
426
  BFD_ASSERT (r_type < (unsigned int) R_CRX_MAX);
427
  cache_ptr->howto = &crx_elf_howto_table[r_type];
428
}
429
 
430
/* Perform a relocation as part of a final link.  */
431
 
432
static bfd_reloc_status_type
433
crx_elf_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd,
434
                             bfd *output_bfd ATTRIBUTE_UNUSED,
435
                             asection *input_section, bfd_byte *contents,
436
                             bfd_vma offset, bfd_vma Rvalue, bfd_vma addend,
437
                             struct bfd_link_info *info ATTRIBUTE_UNUSED,
438
                             asection *sec ATTRIBUTE_UNUSED,
439
                             int is_local ATTRIBUTE_UNUSED)
440
{
441
  unsigned short r_type = howto->type;
442
  bfd_byte *hit_data = contents + offset;
443
  bfd_vma reloc_bits, check;
444
 
445
  switch (r_type)
446
    {
447
     case R_CRX_IMM16:
448
     case R_CRX_IMM32:
449
     case R_CRX_ABS16:
450
     case R_CRX_ABS32:
451
     case R_CRX_REL8_CMP:
452
     case R_CRX_REL16:
453
     case R_CRX_REL24:
454
     case R_CRX_REL32:
455
     case R_CRX_REGREL12:
456
     case R_CRX_REGREL22:
457
     case R_CRX_REGREL28:
458
     case R_CRX_REGREL32:
459
       /* 'hit_data' is relative to the start of the instruction, not the
460
          relocation offset. Advance it to account for the exact offset.  */
461
       hit_data += 2;
462
       break;
463
 
464
     case R_CRX_REL4:
465
       /* This relocation type is used only in 'Branch if Equal to 0'
466
          instructions and requires special handling.  */
467
       Rvalue -= 1;
468
       break;
469
 
470
     case R_CRX_NONE:
471
       return bfd_reloc_ok;
472
       break;
473
 
474
     case R_CRX_SWITCH8:
475
     case R_CRX_SWITCH16:
476
     case R_CRX_SWITCH32:
477
       /* We only care about the addend, where the difference between
478
          expressions is kept.  */
479
       Rvalue = 0;
480
 
481
     default:
482
       break;
483
    }
484
 
485
  if (howto->pc_relative)
486
    {
487
      /* Subtract the address of the section containing the location.  */
488
      Rvalue -= (input_section->output_section->vma
489
                 + input_section->output_offset);
490
      /* Subtract the position of the location within the section.  */
491
      Rvalue -= offset;
492
    }
493
 
494
  /* Add in supplied addend.  */
495
  Rvalue += addend;
496
 
497
  /* Complain if the bitfield overflows, whether it is considered
498
     as signed or unsigned.  */
499
  check = Rvalue >> howto->rightshift;
500
 
501
  /* Assumes two's complement.  This expression avoids
502
     overflow if howto->bitsize is the number of bits in
503
     bfd_vma.  */
504
  reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
505
 
506
  if (((bfd_vma) check & ~reloc_bits) != 0
507
      && (((bfd_vma) check & ~reloc_bits)
508
          != (-(bfd_vma) 1 & ~reloc_bits)))
509
    {
510
      /* The above right shift is incorrect for a signed
511
         value.  See if turning on the upper bits fixes the
512
         overflow.  */
513
      if (howto->rightshift && (bfd_signed_vma) Rvalue < 0)
514
        {
515
          check |= ((bfd_vma) - 1
516
                    & ~((bfd_vma) - 1
517
                        >> howto->rightshift));
518
          if (((bfd_vma) check & ~reloc_bits)
519
              != (-(bfd_vma) 1 & ~reloc_bits))
520
            return bfd_reloc_overflow;
521
        }
522
      else
523
        return bfd_reloc_overflow;
524
    }
525
 
526
  /* Drop unwanted bits from the value we are relocating to.  */
527
  Rvalue >>= (bfd_vma) howto->rightshift;
528
 
529
  /* Apply dst_mask to select only relocatable part of the insn.  */
530
  Rvalue &= howto->dst_mask;
531
 
532
  switch (howto->size)
533
    {
534
     case 0:
535
       if (r_type == R_CRX_REL4)
536
         {
537
           Rvalue <<= 4;
538
           Rvalue |= (bfd_get_8 (input_bfd, hit_data) & 0x0f);
539
         }
540
 
541
       bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data);
542
       break;
543
 
544
     case 1:
545
       if (r_type == R_CRX_REGREL12)
546
         Rvalue |= (bfd_get_16 (input_bfd, hit_data) & 0xf000);
547
 
548
       bfd_put_16 (input_bfd, Rvalue, hit_data);
549
       break;
550
 
551
     case 2:
552
       if (r_type == R_CRX_REL24
553
           || r_type == R_CRX_REGREL22
554
           || r_type == R_CRX_REGREL28)
555
         Rvalue |= (((bfd_get_16 (input_bfd, hit_data) << 16) |
556
                      bfd_get_16 (input_bfd, hit_data + 2)) & ~howto->dst_mask);
557
 
558
       if (r_type == R_CRX_NUM32 || r_type == R_CRX_SWITCH32)
559
         /* Relocation on DATA is purely little-endian, that is, for a
560
            multi-byte datum, the lowest address in memory contains the
561
            little end of the datum, that is, the least significant byte.
562
            Therefore we use BFD's byte Putting functions.  */
563
         bfd_put_32 (input_bfd, Rvalue, hit_data);
564
       else
565
         /* Relocation on INSTRUCTIONS is different : Instructions are
566
            word-addressable, that is, each word itself is arranged according
567
            to little-endian convention, whereas the words are arranged with
568
            respect to one another in BIG ENDIAN fashion.
569
            When there is an immediate value that spans a word boundary, it is
570
            split in a big-endian way with respect to the words.  */
571
         {
572
           bfd_put_16 (input_bfd, (Rvalue >> 16) & 0xffff, hit_data);
573
           bfd_put_16 (input_bfd, Rvalue & 0xffff, hit_data + 2);
574
         }
575
     break;
576
 
577
     default:
578
       return bfd_reloc_notsupported;
579
    }
580
 
581
  return bfd_reloc_ok;
582
}
583
 
584
/* Delete some bytes from a section while relaxing.  */
585
 
586
static bfd_boolean
587
elf32_crx_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
588
                              asection *sec, bfd_vma addr, int count)
589
{
590
  Elf_Internal_Shdr *symtab_hdr;
591
  unsigned int sec_shndx;
592
  bfd_byte *contents;
593
  Elf_Internal_Rela *irel, *irelend;
594
  Elf_Internal_Rela *irelalign;
595
  bfd_vma toaddr;
596
  Elf_Internal_Sym *isym;
597
  Elf_Internal_Sym *isymend;
598
  struct elf_link_hash_entry **sym_hashes;
599
  struct elf_link_hash_entry **end_hashes;
600
  struct elf_link_hash_entry **start_hashes;
601
  unsigned int symcount;
602
 
603
  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
604
 
605
  contents = elf_section_data (sec)->this_hdr.contents;
606
 
607
  /* The deletion must stop at the next ALIGN reloc for an aligment
608
     power larger than the number of bytes we are deleting.  */
609
 
610
  irelalign = NULL;
611
  toaddr = sec->size;
612
 
613
  irel = elf_section_data (sec)->relocs;
614
  irelend = irel + sec->reloc_count;
615
 
616
  /* Actually delete the bytes.  */
617
  memmove (contents + addr, contents + addr + count,
618
           (size_t) (toaddr - addr - count));
619
  sec->size -= count;
620
 
621
  /* Adjust all the relocs.  */
622
  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
623
    {
624
      /* Get the new reloc address.  */
625
      if ((irel->r_offset > addr
626
           && irel->r_offset < toaddr))
627
        irel->r_offset -= count;
628
    }
629
 
630
  /* Adjust the local symbols defined in this section.  */
631
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
632
  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
633
  for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
634
    {
635
      if (isym->st_shndx == sec_shndx
636
          && isym->st_value > addr
637
          && isym->st_value < toaddr)
638
        {
639
          /* Adjust the addend of SWITCH relocations in this section,
640
             which reference this local symbol.  */
641
          for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
642
            {
643
              unsigned long r_symndx;
644
              Elf_Internal_Sym *rsym;
645
              bfd_vma addsym, subsym;
646
 
647
              /* Skip if not a SWITCH relocation.  */
648
              if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH8
649
                  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH16
650
                  && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH32)
651
                  continue;
652
 
653
              r_symndx = ELF32_R_SYM (irel->r_info);
654
              rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
655
 
656
              /* Skip if not the local adjusted symbol.  */
657
              if (rsym != isym)
658
                continue;
659
 
660
              addsym = isym->st_value;
661
              subsym = addsym - irel->r_addend;
662
 
663
              /* Fix the addend only when -->> (addsym > addr >= subsym).  */
664
              if (subsym <= addr)
665
                irel->r_addend -= count;
666
              else
667
                continue;
668
            }
669
 
670
          isym->st_value -= count;
671
        }
672
    }
673
 
674
  /* Now adjust the global symbols defined in this section.  */
675
  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
676
              - symtab_hdr->sh_info);
677
  sym_hashes = start_hashes = elf_sym_hashes (abfd);
678
  end_hashes = sym_hashes + symcount;
679
 
680
  for (; sym_hashes < end_hashes; sym_hashes++)
681
    {
682
      struct elf_link_hash_entry *sym_hash = *sym_hashes;
683
 
684
      /* The '--wrap SYMBOL' option is causing a pain when the object file,
685
         containing the definition of __wrap_SYMBOL, includes a direct
686
         call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
687
         the same symbol (which is __wrap_SYMBOL), but still exist as two
688
         different symbols in 'sym_hashes', we don't want to adjust
689
         the global symbol __wrap_SYMBOL twice.
690
         This check is only relevant when symbols are being wrapped.  */
691
      if (link_info->wrap_hash != NULL)
692
        {
693
          struct elf_link_hash_entry **cur_sym_hashes;
694
 
695
          /* Loop only over the symbols whom been already checked.  */
696
          for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
697
               cur_sym_hashes++)
698
            {
699
              /* If the current symbol is identical to 'sym_hash', that means
700
                 the symbol was already adjusted (or at least checked).  */
701
              if (*cur_sym_hashes == sym_hash)
702
                break;
703
            }
704
          /* Don't adjust the symbol again.  */
705
          if (cur_sym_hashes < sym_hashes)
706
            continue;
707
        }
708
 
709
      if ((sym_hash->root.type == bfd_link_hash_defined
710
           || sym_hash->root.type == bfd_link_hash_defweak)
711
          && sym_hash->root.u.def.section == sec
712
          && sym_hash->root.u.def.value > addr
713
          && sym_hash->root.u.def.value < toaddr)
714
        sym_hash->root.u.def.value -= count;
715
    }
716
 
717
  return TRUE;
718
}
719
 
720
/* This is a version of bfd_generic_get_relocated_section_contents
721
   which uses elf32_crx_relocate_section.  */
722
 
723
static bfd_byte *
724
elf32_crx_get_relocated_section_contents (bfd *output_bfd,
725
                                          struct bfd_link_info *link_info,
726
                                          struct bfd_link_order *link_order,
727
                                          bfd_byte *data,
728
                                          bfd_boolean relocatable,
729
                                          asymbol **symbols)
730
{
731
  Elf_Internal_Shdr *symtab_hdr;
732
  asection *input_section = link_order->u.indirect.section;
733
  bfd *input_bfd = input_section->owner;
734
  asection **sections = NULL;
735
  Elf_Internal_Rela *internal_relocs = NULL;
736
  Elf_Internal_Sym *isymbuf = NULL;
737
 
738
  /* We only need to handle the case of relaxing, or of having a
739
     particular set of section contents, specially.  */
740
  if (relocatable
741
      || elf_section_data (input_section)->this_hdr.contents == NULL)
742
    return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
743
                                                       link_order, data,
744
                                                       relocatable,
745
                                                       symbols);
746
 
747
  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
748
 
749
  memcpy (data, elf_section_data (input_section)->this_hdr.contents,
750
          (size_t) input_section->size);
751
 
752
  if ((input_section->flags & SEC_RELOC) != 0
753
      && input_section->reloc_count > 0)
754
    {
755
      Elf_Internal_Sym *isym;
756
      Elf_Internal_Sym *isymend;
757
      asection **secpp;
758
      bfd_size_type amt;
759
 
760
      internal_relocs = (_bfd_elf_link_read_relocs
761
                         (input_bfd, input_section, (PTR) NULL,
762
                          (Elf_Internal_Rela *) NULL, FALSE));
763
      if (internal_relocs == NULL)
764
        goto error_return;
765
 
766
      if (symtab_hdr->sh_info != 0)
767
        {
768
          isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
769
          if (isymbuf == NULL)
770
            isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
771
                                            symtab_hdr->sh_info, 0,
772
                                            NULL, NULL, NULL);
773
          if (isymbuf == NULL)
774
            goto error_return;
775
        }
776
 
777
      amt = symtab_hdr->sh_info;
778
      amt *= sizeof (asection *);
779
      sections = bfd_malloc (amt);
780
      if (sections == NULL && amt != 0)
781
        goto error_return;
782
 
783
      isymend = isymbuf + symtab_hdr->sh_info;
784
      for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
785
        {
786
          asection *isec;
787
 
788
          if (isym->st_shndx == SHN_UNDEF)
789
            isec = bfd_und_section_ptr;
790
          else if (isym->st_shndx == SHN_ABS)
791
            isec = bfd_abs_section_ptr;
792
          else if (isym->st_shndx == SHN_COMMON)
793
            isec = bfd_com_section_ptr;
794
          else
795
            isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
796
 
797
          *secpp = isec;
798
        }
799
 
800
      if (! elf32_crx_relocate_section (output_bfd, link_info, input_bfd,
801
                                     input_section, data, internal_relocs,
802
                                     isymbuf, sections))
803
        goto error_return;
804
 
805
      if (sections != NULL)
806
        free (sections);
807
      if (isymbuf != NULL
808
          && symtab_hdr->contents != (unsigned char *) isymbuf)
809
        free (isymbuf);
810
      if (elf_section_data (input_section)->relocs != internal_relocs)
811
        free (internal_relocs);
812
    }
813
 
814
  return data;
815
 
816
 error_return:
817
  if (sections != NULL)
818
    free (sections);
819
  if (isymbuf != NULL
820
      && symtab_hdr->contents != (unsigned char *) isymbuf)
821
    free (isymbuf);
822
  if (internal_relocs != NULL
823
      && elf_section_data (input_section)->relocs != internal_relocs)
824
    free (internal_relocs);
825
  return NULL;
826
}
827
 
828
/* Relocate a CRX ELF section.  */
829
 
830
static bfd_boolean
831
elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
832
                            bfd *input_bfd, asection *input_section,
833
                            bfd_byte *contents, Elf_Internal_Rela *relocs,
834
                            Elf_Internal_Sym *local_syms,
835
                            asection **local_sections)
836
{
837
  Elf_Internal_Shdr *symtab_hdr;
838
  struct elf_link_hash_entry **sym_hashes;
839
  Elf_Internal_Rela *rel, *relend;
840
 
841
  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
842
  sym_hashes = elf_sym_hashes (input_bfd);
843
 
844
  rel = relocs;
845
  relend = relocs + input_section->reloc_count;
846
  for (; rel < relend; rel++)
847
    {
848
      int r_type;
849
      reloc_howto_type *howto;
850
      unsigned long r_symndx;
851
      Elf_Internal_Sym *sym;
852
      asection *sec;
853
      struct elf_link_hash_entry *h;
854
      bfd_vma relocation;
855
      bfd_reloc_status_type r;
856
 
857
      r_symndx = ELF32_R_SYM (rel->r_info);
858
      r_type = ELF32_R_TYPE (rel->r_info);
859
      howto = crx_elf_howto_table + (r_type);
860
 
861
      h = NULL;
862
      sym = NULL;
863
      sec = NULL;
864
      if (r_symndx < symtab_hdr->sh_info)
865
        {
866
          sym = local_syms + r_symndx;
867
          sec = local_sections[r_symndx];
868
          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
869
        }
870
      else
871
        {
872
          bfd_boolean unresolved_reloc, warned;
873
 
874
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
875
                                   r_symndx, symtab_hdr, sym_hashes,
876
                                   h, sec, relocation,
877
                                   unresolved_reloc, warned);
878
        }
879
 
880
      if (sec != NULL && elf_discarded_section (sec))
881
        {
882
          /* For relocs against symbols from removed linkonce sections,
883
             or sections discarded by a linker script, we just want the
884
             section contents zeroed.  Avoid any special processing.  */
885
          _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
886
          rel->r_info = 0;
887
          rel->r_addend = 0;
888
          continue;
889
        }
890
 
891
      if (info->relocatable)
892
        continue;
893
 
894
      r = crx_elf_final_link_relocate (howto, input_bfd, output_bfd,
895
                                        input_section,
896
                                        contents, rel->r_offset,
897
                                        relocation, rel->r_addend,
898
                                        info, sec, h == NULL);
899
 
900
      if (r != bfd_reloc_ok)
901
        {
902
          const char *name;
903
          const char *msg = (const char *) 0;
904
 
905
          if (h != NULL)
906
            name = h->root.root.string;
907
          else
908
            {
909
              name = (bfd_elf_string_from_elf_section
910
                      (input_bfd, symtab_hdr->sh_link, sym->st_name));
911
              if (name == NULL || *name == '\0')
912
                name = bfd_section_name (input_bfd, sec);
913
            }
914
 
915
          switch (r)
916
            {
917
             case bfd_reloc_overflow:
918
               if (!((*info->callbacks->reloc_overflow)
919
                     (info, (h ? &h->root : NULL), name, howto->name,
920
                      (bfd_vma) 0, input_bfd, input_section,
921
                      rel->r_offset)))
922
                 return FALSE;
923
               break;
924
 
925
             case bfd_reloc_undefined:
926
               if (!((*info->callbacks->undefined_symbol)
927
                     (info, name, input_bfd, input_section,
928
                      rel->r_offset, TRUE)))
929
                 return FALSE;
930
               break;
931
 
932
             case bfd_reloc_outofrange:
933
               msg = _("internal error: out of range error");
934
               goto common_error;
935
 
936
             case bfd_reloc_notsupported:
937
               msg = _("internal error: unsupported relocation error");
938
               goto common_error;
939
 
940
             case bfd_reloc_dangerous:
941
               msg = _("internal error: dangerous error");
942
               goto common_error;
943
 
944
             default:
945
               msg = _("internal error: unknown error");
946
               /* Fall through.  */
947
 
948
             common_error:
949
               if (!((*info->callbacks->warning)
950
                     (info, msg, name, input_bfd, input_section,
951
                      rel->r_offset)))
952
                 return FALSE;
953
               break;
954
            }
955
        }
956
    }
957
 
958
  return TRUE;
959
}
960
 
961
/* This function handles relaxing for the CRX.
962
 
963
   There's quite a few relaxing opportunites available on the CRX:
964
 
965
        * bal/bcond:32 -> bal/bcond:16                             2 bytes
966
        * bcond:16 -> bcond:8                                      2 bytes
967
        * cmpbcond:24 -> cmpbcond:8                                2 bytes
968
        * arithmetic imm32 -> arithmetic imm16                     2 bytes
969
 
970
   Symbol- and reloc-reading infrastructure copied from elf-m10200.c.  */
971
 
972
static bfd_boolean
973
elf32_crx_relax_section (bfd *abfd, asection *sec,
974
                         struct bfd_link_info *link_info, bfd_boolean *again)
975
{
976
  Elf_Internal_Shdr *symtab_hdr;
977
  Elf_Internal_Rela *internal_relocs;
978
  Elf_Internal_Rela *irel, *irelend;
979
  bfd_byte *contents = NULL;
980
  Elf_Internal_Sym *isymbuf = NULL;
981
 
982
  /* Assume nothing changes.  */
983
  *again = FALSE;
984
 
985
  /* We don't have to do anything for a relocatable link, if
986
     this section does not have relocs, or if this is not a
987
     code section.  */
988
  if (link_info->relocatable
989
      || (sec->flags & SEC_RELOC) == 0
990
      || sec->reloc_count == 0
991
      || (sec->flags & SEC_CODE) == 0)
992
    return TRUE;
993
 
994
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
995
 
996
  /* Get a copy of the native relocations.  */
997
  internal_relocs = (_bfd_elf_link_read_relocs
998
                     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
999
                      link_info->keep_memory));
1000
  if (internal_relocs == NULL)
1001
    goto error_return;
1002
 
1003
  /* Walk through them looking for relaxing opportunities.  */
1004
  irelend = internal_relocs + sec->reloc_count;
1005
  for (irel = internal_relocs; irel < irelend; irel++)
1006
    {
1007
      bfd_vma symval;
1008
 
1009
      /* If this isn't something that can be relaxed, then ignore
1010
         this reloc.  */
1011
      if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL32
1012
          && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL16
1013
          && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL24
1014
          && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_IMM32)
1015
        continue;
1016
 
1017
      /* Get the section contents if we haven't done so already.  */
1018
      if (contents == NULL)
1019
        {
1020
          /* Get cached copy if it exists.  */
1021
          if (elf_section_data (sec)->this_hdr.contents != NULL)
1022
            contents = elf_section_data (sec)->this_hdr.contents;
1023
          /* Go get them off disk.  */
1024
          else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
1025
            goto error_return;
1026
        }
1027
 
1028
      /* Read this BFD's local symbols if we haven't done so already.  */
1029
      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1030
        {
1031
          isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1032
          if (isymbuf == NULL)
1033
            isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1034
                                            symtab_hdr->sh_info, 0,
1035
                                            NULL, NULL, NULL);
1036
          if (isymbuf == NULL)
1037
            goto error_return;
1038
        }
1039
 
1040
      /* Get the value of the symbol referred to by the reloc.  */
1041
      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1042
        {
1043
          /* A local symbol.  */
1044
          Elf_Internal_Sym *isym;
1045
          asection *sym_sec;
1046
 
1047
          isym = isymbuf + ELF32_R_SYM (irel->r_info);
1048
          if (isym->st_shndx == SHN_UNDEF)
1049
            sym_sec = bfd_und_section_ptr;
1050
          else if (isym->st_shndx == SHN_ABS)
1051
            sym_sec = bfd_abs_section_ptr;
1052
          else if (isym->st_shndx == SHN_COMMON)
1053
            sym_sec = bfd_com_section_ptr;
1054
          else
1055
            sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1056
          symval = (isym->st_value
1057
                    + sym_sec->output_section->vma
1058
                    + sym_sec->output_offset);
1059
        }
1060
      else
1061
        {
1062
          unsigned long indx;
1063
          struct elf_link_hash_entry *h;
1064
 
1065
          /* An external symbol.  */
1066
          indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1067
          h = elf_sym_hashes (abfd)[indx];
1068
          BFD_ASSERT (h != NULL);
1069
 
1070
          if (h->root.type != bfd_link_hash_defined
1071
              && h->root.type != bfd_link_hash_defweak)
1072
            /* This appears to be a reference to an undefined
1073
               symbol.  Just ignore it--it will be caught by the
1074
               regular reloc processing.  */
1075
            continue;
1076
 
1077
          symval = (h->root.u.def.value
1078
                    + h->root.u.def.section->output_section->vma
1079
                    + h->root.u.def.section->output_offset);
1080
        }
1081
 
1082
      /* For simplicity of coding, we are going to modify the section
1083
         contents, the section relocs, and the BFD symbol table.  We
1084
         must tell the rest of the code not to free up this
1085
         information.  It would be possible to instead create a table
1086
         of changes which have to be made, as is done in coff-mips.c;
1087
         that would be more work, but would require less memory when
1088
         the linker is run.  */
1089
 
1090
      /* Try to turn a 32bit pc-relative branch/call into
1091
         a 16bit pc-relative branch/call.  */
1092
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL32)
1093
        {
1094
          bfd_vma value = symval;
1095
 
1096
          /* Deal with pc-relative gunk.  */
1097
          value -= (sec->output_section->vma + sec->output_offset);
1098
          value -= irel->r_offset;
1099
          value += irel->r_addend;
1100
 
1101
          /* See if the value will fit in 16 bits, note the high value is
1102
             0xfffe + 2 as the target will be two bytes closer if we are
1103
             able to relax.  */
1104
          if ((long) value < 0x10000 && (long) value > -0x10002)
1105
            {
1106
              unsigned short code;
1107
 
1108
              /* Get the opcode.  */
1109
              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1110
 
1111
              /* Verify it's a 'bal'/'bcond' and fix the opcode.  */
1112
              if ((code & 0xfff0) == 0x3170)
1113
                bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1114
              else if ((code & 0xf0ff) == 0x707f)
1115
                bfd_put_8 (abfd, 0x7e, contents + irel->r_offset);
1116
              else
1117
                continue;
1118
 
1119
              /* Note that we've changed the relocs, section contents, etc.  */
1120
              elf_section_data (sec)->relocs = internal_relocs;
1121
              elf_section_data (sec)->this_hdr.contents = contents;
1122
              symtab_hdr->contents = (unsigned char *) isymbuf;
1123
 
1124
              /* Fix the relocation's type.  */
1125
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1126
                                           R_CRX_REL16);
1127
 
1128
              /* Delete two bytes of data.  */
1129
              if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1130
                                                   irel->r_offset + 2, 2))
1131
                goto error_return;
1132
 
1133
              /* That will change things, so, we should relax again.
1134
                 Note that this is not required, and it may be slow.  */
1135
              *again = TRUE;
1136
            }
1137
        }
1138
 
1139
      /* Try to turn a 16bit pc-relative branch into an
1140
         8bit pc-relative branch.  */
1141
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL16)
1142
        {
1143
          bfd_vma value = symval;
1144
 
1145
          /* Deal with pc-relative gunk.  */
1146
          value -= (sec->output_section->vma + sec->output_offset);
1147
          value -= irel->r_offset;
1148
          value += irel->r_addend;
1149
 
1150
          /* See if the value will fit in 8 bits, note the high value is
1151
             0xfc + 2 as the target will be two bytes closer if we are
1152
             able to relax.  */
1153
          if ((long) value < 0xfe && (long) value > -0x100)
1154
            {
1155
              unsigned short code;
1156
 
1157
              /* Get the opcode.  */
1158
              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1159
 
1160
              /* Verify it's a 'bcond' opcode.  */
1161
              if ((code & 0xf0ff) != 0x707e)
1162
                continue;
1163
 
1164
              /* Note that we've changed the relocs, section contents, etc.  */
1165
              elf_section_data (sec)->relocs = internal_relocs;
1166
              elf_section_data (sec)->this_hdr.contents = contents;
1167
              symtab_hdr->contents = (unsigned char *) isymbuf;
1168
 
1169
              /* Fix the relocation's type.  */
1170
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1171
                                           R_CRX_REL8);
1172
 
1173
              /* Delete two bytes of data.  */
1174
              if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1175
                                                   irel->r_offset + 2, 2))
1176
                goto error_return;
1177
 
1178
              /* That will change things, so, we should relax again.
1179
                 Note that this is not required, and it may be slow.  */
1180
              *again = TRUE;
1181
            }
1182
        }
1183
 
1184
      /* Try to turn a 24bit pc-relative cmp&branch into
1185
         an 8bit pc-relative cmp&branch.  */
1186
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL24)
1187
        {
1188
          bfd_vma value = symval;
1189
 
1190
          /* Deal with pc-relative gunk.  */
1191
          value -= (sec->output_section->vma + sec->output_offset);
1192
          value -= irel->r_offset;
1193
          value += irel->r_addend;
1194
 
1195
          /* See if the value will fit in 8 bits, note the high value is
1196
             0x7e + 2 as the target will be two bytes closer if we are
1197
             able to relax.  */
1198
          if ((long) value < 0x100 && (long) value > -0x100)
1199
            {
1200
              unsigned short code;
1201
 
1202
              /* Get the opcode.  */
1203
              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1204
 
1205
              /* Verify it's a 'cmp&branch' opcode.  */
1206
              if ((code & 0xfff0) != 0x3180 && (code & 0xfff0) != 0x3190
1207
               && (code & 0xfff0) != 0x31a0 && (code & 0xfff0) != 0x31c0
1208
               && (code & 0xfff0) != 0x31d0 && (code & 0xfff0) != 0x31e0
1209
               /* Or a Co-processor branch ('bcop').  */
1210
               && (code & 0xfff0) != 0x3010 && (code & 0xfff0) != 0x3110)
1211
                continue;
1212
 
1213
              /* Note that we've changed the relocs, section contents, etc.  */
1214
              elf_section_data (sec)->relocs = internal_relocs;
1215
              elf_section_data (sec)->this_hdr.contents = contents;
1216
              symtab_hdr->contents = (unsigned char *) isymbuf;
1217
 
1218
              /* Fix the opcode.  */
1219
              bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1220
 
1221
              /* Fix the relocation's type.  */
1222
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1223
                                           R_CRX_REL8_CMP);
1224
 
1225
              /* Delete two bytes of data.  */
1226
              if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1227
                                                   irel->r_offset + 4, 2))
1228
                goto error_return;
1229
 
1230
              /* That will change things, so, we should relax again.
1231
                 Note that this is not required, and it may be slow.  */
1232
              *again = TRUE;
1233
            }
1234
        }
1235
 
1236
      /* Try to turn a 32bit immediate address into
1237
         a 16bit immediate address.  */
1238
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_IMM32)
1239
        {
1240
          bfd_vma value = symval;
1241
 
1242
          /* See if the value will fit in 16 bits.  */
1243
          if ((long) value < 0x7fff && (long) value > -0x8000)
1244
            {
1245
              unsigned short code;
1246
 
1247
              /* Get the opcode.  */
1248
              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1249
 
1250
              /* Verify it's a 'arithmetic double'.  */
1251
              if ((code & 0xf0f0) != 0x20f0)
1252
                continue;
1253
 
1254
              /* Note that we've changed the relocs, section contents, etc.  */
1255
              elf_section_data (sec)->relocs = internal_relocs;
1256
              elf_section_data (sec)->this_hdr.contents = contents;
1257
              symtab_hdr->contents = (unsigned char *) isymbuf;
1258
 
1259
              /* Fix the opcode.  */
1260
              bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
1261
 
1262
              /* Fix the relocation's type.  */
1263
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1264
                                           R_CRX_IMM16);
1265
 
1266
              /* Delete two bytes of data.  */
1267
              if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1268
                                                   irel->r_offset + 2, 2))
1269
                goto error_return;
1270
 
1271
              /* That will change things, so, we should relax again.
1272
                 Note that this is not required, and it may be slow.  */
1273
              *again = TRUE;
1274
            }
1275
        }
1276
    }
1277
 
1278
  if (isymbuf != NULL
1279
      && symtab_hdr->contents != (unsigned char *) isymbuf)
1280
    {
1281
      if (! link_info->keep_memory)
1282
        free (isymbuf);
1283
      else
1284
        {
1285
          /* Cache the symbols for elf_link_input_bfd.  */
1286
          symtab_hdr->contents = (unsigned char *) isymbuf;
1287
        }
1288
    }
1289
 
1290
  if (contents != NULL
1291
      && elf_section_data (sec)->this_hdr.contents != contents)
1292
    {
1293
      if (! link_info->keep_memory)
1294
        free (contents);
1295
      else
1296
        {
1297
          /* Cache the section contents for elf_link_input_bfd.  */
1298
          elf_section_data (sec)->this_hdr.contents = contents;
1299
        }
1300
    }
1301
 
1302
  if (internal_relocs != NULL
1303
      && elf_section_data (sec)->relocs != internal_relocs)
1304
    free (internal_relocs);
1305
 
1306
  return TRUE;
1307
 
1308
 error_return:
1309
  if (isymbuf != NULL
1310
      && symtab_hdr->contents != (unsigned char *) isymbuf)
1311
    free (isymbuf);
1312
  if (contents != NULL
1313
      && elf_section_data (sec)->this_hdr.contents != contents)
1314
    free (contents);
1315
  if (internal_relocs != NULL
1316
      && elf_section_data (sec)->relocs != internal_relocs)
1317
    free (internal_relocs);
1318
 
1319
  return FALSE;
1320
}
1321
 
1322
/* Definitions for setting CRX target vector.  */
1323
#define TARGET_LITTLE_SYM               bfd_elf32_crx_vec
1324
#define TARGET_LITTLE_NAME              "elf32-crx"
1325
#define ELF_ARCH                        bfd_arch_crx
1326
#define ELF_MACHINE_CODE                EM_CRX
1327
#define ELF_MAXPAGESIZE                 0x1
1328
#define elf_symbol_leading_char         '_'
1329
 
1330
#define bfd_elf32_bfd_reloc_type_lookup elf_crx_reloc_type_lookup
1331
#define bfd_elf32_bfd_reloc_name_lookup \
1332
                                        elf_crx_reloc_name_lookup
1333
#define elf_info_to_howto               elf_crx_info_to_howto
1334
#define elf_info_to_howto_rel           0
1335
#define elf_backend_relocate_section    elf32_crx_relocate_section
1336
#define bfd_elf32_bfd_relax_section     elf32_crx_relax_section
1337
#define bfd_elf32_bfd_get_relocated_section_contents \
1338
                                elf32_crx_get_relocated_section_contents
1339
#define elf_backend_can_gc_sections     1
1340
#define elf_backend_rela_normal         1
1341
 
1342
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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