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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [bfd/] [elf32-crx.c] - Blame information for rev 841

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 330 jeremybenn
/* 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
        {
878
          /* For relocs against symbols from removed linkonce sections,
879
             or sections discarded by a linker script, we just want the
880
             section contents zeroed.  Avoid any special processing.  */
881
          _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
882
          rel->r_info = 0;
883
          rel->r_addend = 0;
884
          continue;
885
        }
886
 
887
      if (info->relocatable)
888
        continue;
889
 
890
      r = crx_elf_final_link_relocate (howto, input_bfd, output_bfd,
891
                                        input_section,
892
                                        contents, rel->r_offset,
893
                                        relocation, rel->r_addend,
894
                                        info, sec, h == NULL);
895
 
896
      if (r != bfd_reloc_ok)
897
        {
898
          const char *name;
899
          const char *msg = (const char *) 0;
900
 
901
          if (h != NULL)
902
            name = h->root.root.string;
903
          else
904
            {
905
              name = (bfd_elf_string_from_elf_section
906
                      (input_bfd, symtab_hdr->sh_link, sym->st_name));
907
              if (name == NULL || *name == '\0')
908
                name = bfd_section_name (input_bfd, sec);
909
            }
910
 
911
          switch (r)
912
            {
913
             case bfd_reloc_overflow:
914
               if (!((*info->callbacks->reloc_overflow)
915
                     (info, (h ? &h->root : NULL), name, howto->name,
916
                      (bfd_vma) 0, input_bfd, input_section,
917
                      rel->r_offset)))
918
                 return FALSE;
919
               break;
920
 
921
             case bfd_reloc_undefined:
922
               if (!((*info->callbacks->undefined_symbol)
923
                     (info, name, input_bfd, input_section,
924
                      rel->r_offset, TRUE)))
925
                 return FALSE;
926
               break;
927
 
928
             case bfd_reloc_outofrange:
929
               msg = _("internal error: out of range error");
930
               goto common_error;
931
 
932
             case bfd_reloc_notsupported:
933
               msg = _("internal error: unsupported relocation error");
934
               goto common_error;
935
 
936
             case bfd_reloc_dangerous:
937
               msg = _("internal error: dangerous error");
938
               goto common_error;
939
 
940
             default:
941
               msg = _("internal error: unknown error");
942
               /* Fall through.  */
943
 
944
             common_error:
945
               if (!((*info->callbacks->warning)
946
                     (info, msg, name, input_bfd, input_section,
947
                      rel->r_offset)))
948
                 return FALSE;
949
               break;
950
            }
951
        }
952
    }
953
 
954
  return TRUE;
955
}
956
 
957
/* This function handles relaxing for the CRX.
958
 
959
   There's quite a few relaxing opportunites available on the CRX:
960
 
961
        * bal/bcond:32 -> bal/bcond:16                             2 bytes
962
        * bcond:16 -> bcond:8                                      2 bytes
963
        * cmpbcond:24 -> cmpbcond:8                                2 bytes
964
        * arithmetic imm32 -> arithmetic imm16                     2 bytes
965
 
966
   Symbol- and reloc-reading infrastructure copied from elf-m10200.c.  */
967
 
968
static bfd_boolean
969
elf32_crx_relax_section (bfd *abfd, asection *sec,
970
                         struct bfd_link_info *link_info, bfd_boolean *again)
971
{
972
  Elf_Internal_Shdr *symtab_hdr;
973
  Elf_Internal_Rela *internal_relocs;
974
  Elf_Internal_Rela *irel, *irelend;
975
  bfd_byte *contents = NULL;
976
  Elf_Internal_Sym *isymbuf = NULL;
977
 
978
  /* Assume nothing changes.  */
979
  *again = FALSE;
980
 
981
  /* We don't have to do anything for a relocatable link, if
982
     this section does not have relocs, or if this is not a
983
     code section.  */
984
  if (link_info->relocatable
985
      || (sec->flags & SEC_RELOC) == 0
986
      || sec->reloc_count == 0
987
      || (sec->flags & SEC_CODE) == 0)
988
    return TRUE;
989
 
990
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
991
 
992
  /* Get a copy of the native relocations.  */
993
  internal_relocs = (_bfd_elf_link_read_relocs
994
                     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
995
                      link_info->keep_memory));
996
  if (internal_relocs == NULL)
997
    goto error_return;
998
 
999
  /* Walk through them looking for relaxing opportunities.  */
1000
  irelend = internal_relocs + sec->reloc_count;
1001
  for (irel = internal_relocs; irel < irelend; irel++)
1002
    {
1003
      bfd_vma symval;
1004
 
1005
      /* If this isn't something that can be relaxed, then ignore
1006
         this reloc.  */
1007
      if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL32
1008
          && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL16
1009
          && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL24
1010
          && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_IMM32)
1011
        continue;
1012
 
1013
      /* Get the section contents if we haven't done so already.  */
1014
      if (contents == NULL)
1015
        {
1016
          /* Get cached copy if it exists.  */
1017
          if (elf_section_data (sec)->this_hdr.contents != NULL)
1018
            contents = elf_section_data (sec)->this_hdr.contents;
1019
          /* Go get them off disk.  */
1020
          else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
1021
            goto error_return;
1022
        }
1023
 
1024
      /* Read this BFD's local symbols if we haven't done so already.  */
1025
      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1026
        {
1027
          isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1028
          if (isymbuf == NULL)
1029
            isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1030
                                            symtab_hdr->sh_info, 0,
1031
                                            NULL, NULL, NULL);
1032
          if (isymbuf == NULL)
1033
            goto error_return;
1034
        }
1035
 
1036
      /* Get the value of the symbol referred to by the reloc.  */
1037
      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1038
        {
1039
          /* A local symbol.  */
1040
          Elf_Internal_Sym *isym;
1041
          asection *sym_sec;
1042
 
1043
          isym = isymbuf + ELF32_R_SYM (irel->r_info);
1044
          if (isym->st_shndx == SHN_UNDEF)
1045
            sym_sec = bfd_und_section_ptr;
1046
          else if (isym->st_shndx == SHN_ABS)
1047
            sym_sec = bfd_abs_section_ptr;
1048
          else if (isym->st_shndx == SHN_COMMON)
1049
            sym_sec = bfd_com_section_ptr;
1050
          else
1051
            sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1052
          symval = (isym->st_value
1053
                    + sym_sec->output_section->vma
1054
                    + sym_sec->output_offset);
1055
        }
1056
      else
1057
        {
1058
          unsigned long indx;
1059
          struct elf_link_hash_entry *h;
1060
 
1061
          /* An external symbol.  */
1062
          indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1063
          h = elf_sym_hashes (abfd)[indx];
1064
          BFD_ASSERT (h != NULL);
1065
 
1066
          if (h->root.type != bfd_link_hash_defined
1067
              && h->root.type != bfd_link_hash_defweak)
1068
            /* This appears to be a reference to an undefined
1069
               symbol.  Just ignore it--it will be caught by the
1070
               regular reloc processing.  */
1071
            continue;
1072
 
1073
          symval = (h->root.u.def.value
1074
                    + h->root.u.def.section->output_section->vma
1075
                    + h->root.u.def.section->output_offset);
1076
        }
1077
 
1078
      /* For simplicity of coding, we are going to modify the section
1079
         contents, the section relocs, and the BFD symbol table.  We
1080
         must tell the rest of the code not to free up this
1081
         information.  It would be possible to instead create a table
1082
         of changes which have to be made, as is done in coff-mips.c;
1083
         that would be more work, but would require less memory when
1084
         the linker is run.  */
1085
 
1086
      /* Try to turn a 32bit pc-relative branch/call into
1087
         a 16bit pc-relative branch/call.  */
1088
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL32)
1089
        {
1090
          bfd_vma value = symval;
1091
 
1092
          /* Deal with pc-relative gunk.  */
1093
          value -= (sec->output_section->vma + sec->output_offset);
1094
          value -= irel->r_offset;
1095
          value += irel->r_addend;
1096
 
1097
          /* See if the value will fit in 16 bits, note the high value is
1098
             0xfffe + 2 as the target will be two bytes closer if we are
1099
             able to relax.  */
1100
          if ((long) value < 0x10000 && (long) value > -0x10002)
1101
            {
1102
              unsigned short code;
1103
 
1104
              /* Get the opcode.  */
1105
              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1106
 
1107
              /* Verify it's a 'bal'/'bcond' and fix the opcode.  */
1108
              if ((code & 0xfff0) == 0x3170)
1109
                bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1110
              else if ((code & 0xf0ff) == 0x707f)
1111
                bfd_put_8 (abfd, 0x7e, contents + irel->r_offset);
1112
              else
1113
                continue;
1114
 
1115
              /* Note that we've changed the relocs, section contents, etc.  */
1116
              elf_section_data (sec)->relocs = internal_relocs;
1117
              elf_section_data (sec)->this_hdr.contents = contents;
1118
              symtab_hdr->contents = (unsigned char *) isymbuf;
1119
 
1120
              /* Fix the relocation's type.  */
1121
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1122
                                           R_CRX_REL16);
1123
 
1124
              /* Delete two bytes of data.  */
1125
              if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1126
                                                   irel->r_offset + 2, 2))
1127
                goto error_return;
1128
 
1129
              /* That will change things, so, we should relax again.
1130
                 Note that this is not required, and it may be slow.  */
1131
              *again = TRUE;
1132
            }
1133
        }
1134
 
1135
      /* Try to turn a 16bit pc-relative branch into an
1136
         8bit pc-relative branch.  */
1137
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL16)
1138
        {
1139
          bfd_vma value = symval;
1140
 
1141
          /* Deal with pc-relative gunk.  */
1142
          value -= (sec->output_section->vma + sec->output_offset);
1143
          value -= irel->r_offset;
1144
          value += irel->r_addend;
1145
 
1146
          /* See if the value will fit in 8 bits, note the high value is
1147
             0xfc + 2 as the target will be two bytes closer if we are
1148
             able to relax.  */
1149
          if ((long) value < 0xfe && (long) value > -0x100)
1150
            {
1151
              unsigned short code;
1152
 
1153
              /* Get the opcode.  */
1154
              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1155
 
1156
              /* Verify it's a 'bcond' opcode.  */
1157
              if ((code & 0xf0ff) != 0x707e)
1158
                continue;
1159
 
1160
              /* Note that we've changed the relocs, section contents, etc.  */
1161
              elf_section_data (sec)->relocs = internal_relocs;
1162
              elf_section_data (sec)->this_hdr.contents = contents;
1163
              symtab_hdr->contents = (unsigned char *) isymbuf;
1164
 
1165
              /* Fix the relocation's type.  */
1166
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1167
                                           R_CRX_REL8);
1168
 
1169
              /* Delete two bytes of data.  */
1170
              if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1171
                                                   irel->r_offset + 2, 2))
1172
                goto error_return;
1173
 
1174
              /* That will change things, so, we should relax again.
1175
                 Note that this is not required, and it may be slow.  */
1176
              *again = TRUE;
1177
            }
1178
        }
1179
 
1180
      /* Try to turn a 24bit pc-relative cmp&branch into
1181
         an 8bit pc-relative cmp&branch.  */
1182
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL24)
1183
        {
1184
          bfd_vma value = symval;
1185
 
1186
          /* Deal with pc-relative gunk.  */
1187
          value -= (sec->output_section->vma + sec->output_offset);
1188
          value -= irel->r_offset;
1189
          value += irel->r_addend;
1190
 
1191
          /* See if the value will fit in 8 bits, note the high value is
1192
             0x7e + 2 as the target will be two bytes closer if we are
1193
             able to relax.  */
1194
          if ((long) value < 0x100 && (long) value > -0x100)
1195
            {
1196
              unsigned short code;
1197
 
1198
              /* Get the opcode.  */
1199
              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1200
 
1201
              /* Verify it's a 'cmp&branch' opcode.  */
1202
              if ((code & 0xfff0) != 0x3180 && (code & 0xfff0) != 0x3190
1203
               && (code & 0xfff0) != 0x31a0 && (code & 0xfff0) != 0x31c0
1204
               && (code & 0xfff0) != 0x31d0 && (code & 0xfff0) != 0x31e0
1205
               /* Or a Co-processor branch ('bcop').  */
1206
               && (code & 0xfff0) != 0x3010 && (code & 0xfff0) != 0x3110)
1207
                continue;
1208
 
1209
              /* Note that we've changed the relocs, section contents, etc.  */
1210
              elf_section_data (sec)->relocs = internal_relocs;
1211
              elf_section_data (sec)->this_hdr.contents = contents;
1212
              symtab_hdr->contents = (unsigned char *) isymbuf;
1213
 
1214
              /* Fix the opcode.  */
1215
              bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1216
 
1217
              /* Fix the relocation's type.  */
1218
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1219
                                           R_CRX_REL8_CMP);
1220
 
1221
              /* Delete two bytes of data.  */
1222
              if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1223
                                                   irel->r_offset + 4, 2))
1224
                goto error_return;
1225
 
1226
              /* That will change things, so, we should relax again.
1227
                 Note that this is not required, and it may be slow.  */
1228
              *again = TRUE;
1229
            }
1230
        }
1231
 
1232
      /* Try to turn a 32bit immediate address into
1233
         a 16bit immediate address.  */
1234
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_IMM32)
1235
        {
1236
          bfd_vma value = symval;
1237
 
1238
          /* See if the value will fit in 16 bits.  */
1239
          if ((long) value < 0x7fff && (long) value > -0x8000)
1240
            {
1241
              unsigned short code;
1242
 
1243
              /* Get the opcode.  */
1244
              code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1245
 
1246
              /* Verify it's a 'arithmetic double'.  */
1247
              if ((code & 0xf0f0) != 0x20f0)
1248
                continue;
1249
 
1250
              /* Note that we've changed the relocs, section contents, etc.  */
1251
              elf_section_data (sec)->relocs = internal_relocs;
1252
              elf_section_data (sec)->this_hdr.contents = contents;
1253
              symtab_hdr->contents = (unsigned char *) isymbuf;
1254
 
1255
              /* Fix the opcode.  */
1256
              bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
1257
 
1258
              /* Fix the relocation's type.  */
1259
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1260
                                           R_CRX_IMM16);
1261
 
1262
              /* Delete two bytes of data.  */
1263
              if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1264
                                                   irel->r_offset + 2, 2))
1265
                goto error_return;
1266
 
1267
              /* That will change things, so, we should relax again.
1268
                 Note that this is not required, and it may be slow.  */
1269
              *again = TRUE;
1270
            }
1271
        }
1272
    }
1273
 
1274
  if (isymbuf != NULL
1275
      && symtab_hdr->contents != (unsigned char *) isymbuf)
1276
    {
1277
      if (! link_info->keep_memory)
1278
        free (isymbuf);
1279
      else
1280
        {
1281
          /* Cache the symbols for elf_link_input_bfd.  */
1282
          symtab_hdr->contents = (unsigned char *) isymbuf;
1283
        }
1284
    }
1285
 
1286
  if (contents != NULL
1287
      && elf_section_data (sec)->this_hdr.contents != contents)
1288
    {
1289
      if (! link_info->keep_memory)
1290
        free (contents);
1291
      else
1292
        {
1293
          /* Cache the section contents for elf_link_input_bfd.  */
1294
          elf_section_data (sec)->this_hdr.contents = contents;
1295
        }
1296
    }
1297
 
1298
  if (internal_relocs != NULL
1299
      && elf_section_data (sec)->relocs != internal_relocs)
1300
    free (internal_relocs);
1301
 
1302
  return TRUE;
1303
 
1304
 error_return:
1305
  if (isymbuf != NULL
1306
      && symtab_hdr->contents != (unsigned char *) isymbuf)
1307
    free (isymbuf);
1308
  if (contents != NULL
1309
      && elf_section_data (sec)->this_hdr.contents != contents)
1310
    free (contents);
1311
  if (internal_relocs != NULL
1312
      && elf_section_data (sec)->relocs != internal_relocs)
1313
    free (internal_relocs);
1314
 
1315
  return FALSE;
1316
}
1317
 
1318
/* Definitions for setting CRX target vector.  */
1319
#define TARGET_LITTLE_SYM               bfd_elf32_crx_vec
1320
#define TARGET_LITTLE_NAME              "elf32-crx"
1321
#define ELF_ARCH                        bfd_arch_crx
1322
#define ELF_MACHINE_CODE                EM_CRX
1323
#define ELF_MAXPAGESIZE                 0x1
1324
#define elf_symbol_leading_char         '_'
1325
 
1326
#define bfd_elf32_bfd_reloc_type_lookup elf_crx_reloc_type_lookup
1327
#define bfd_elf32_bfd_reloc_name_lookup \
1328
                                        elf_crx_reloc_name_lookup
1329
#define elf_info_to_howto               elf_crx_info_to_howto
1330
#define elf_info_to_howto_rel           0
1331
#define elf_backend_relocate_section    elf32_crx_relocate_section
1332
#define bfd_elf32_bfd_relax_section     elf32_crx_relax_section
1333
#define bfd_elf32_bfd_get_relocated_section_contents \
1334
                                elf32_crx_get_relocated_section_contents
1335
#define elf_backend_can_gc_sections     1
1336
#define elf_backend_rela_normal         1
1337
 
1338
#include "elf32-target.h"

powered by: WebSVN 2.1.0

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