Coverage Report

Created: 2025-06-24 06:45

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