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

Subversion Repositories open8_urisc

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

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

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

powered by: WebSVN 2.1.0

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