Coverage Report

Created: 2026-09-14 08:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/binutils-gdb/bfd/elf32-crx.c
Line
Count
Source
1
/* BFD back-end for National Semiconductor's CRX ELF
2
   Copyright (C) 2004-2026 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
  (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 *, const 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
209
{
425
209
  unsigned int r_type = ELF32_R_TYPE (dst->r_info);
426
209
  if (r_type >= R_CRX_MAX)
427
15
    {
428
      /* xgettext:c-format */
429
15
      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
430
15
        abfd, r_type);
431
15
      bfd_set_error (bfd_error_bad_value);
432
15
      return false;
433
15
    }
434
194
  cache_ptr->howto = &crx_elf_howto_table[r_type];
435
194
  return true;
436
209
}
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_symtab_hdr (abfd);
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
721
  (bfd *output_bfd,
722
   struct bfd_link_info *link_info,
723
   const struct bfd_link_order *link_order,
724
   bfd_byte *data,
725
   bool relocatable,
726
   asymbol **symbols)
727
9
{
728
9
  Elf_Internal_Shdr *symtab_hdr;
729
9
  asection *input_section = link_order->u.indirect.section;
730
9
  bfd *input_bfd = input_section->owner;
731
9
  asection **sections = NULL;
732
9
  Elf_Internal_Rela *internal_relocs = NULL;
733
9
  Elf_Internal_Sym *isymbuf = NULL;
734
735
  /* We only need to handle the case of relaxing, or of having a
736
     particular set of section contents, specially.  */
737
9
  if (relocatable
738
9
      || elf_section_data (input_section)->this_hdr.contents == NULL)
739
9
    return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
740
9
                   link_order, data,
741
9
                   relocatable,
742
9
                   symbols);
743
744
0
  symtab_hdr = &elf_symtab_hdr (input_bfd);
745
746
0
  bfd_byte *orig_data = data;
747
0
  if (data == NULL)
748
0
    {
749
0
      data = bfd_malloc (input_section->size);
750
0
      if (data == NULL)
751
0
  return NULL;
752
0
    }
753
0
  memcpy (data, elf_section_data (input_section)->this_hdr.contents,
754
0
    (size_t) input_section->size);
755
756
0
  if ((input_section->flags & SEC_RELOC) != 0
757
0
      && input_section->reloc_count > 0)
758
0
    {
759
0
      Elf_Internal_Sym *isym;
760
0
      Elf_Internal_Sym *isymend;
761
0
      asection **secpp;
762
0
      bfd_size_type amt;
763
764
0
      internal_relocs = (_bfd_elf_link_read_relocs
765
0
       (input_bfd, input_section, NULL,
766
0
        (Elf_Internal_Rela *) NULL, false));
767
0
      if (internal_relocs == NULL)
768
0
  goto error_return;
769
770
0
      if (symtab_hdr->sh_info != 0)
771
0
  {
772
0
    isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
773
0
    if (isymbuf == NULL)
774
0
      isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
775
0
              symtab_hdr->sh_info, 0,
776
0
              NULL, NULL, NULL);
777
0
    if (isymbuf == NULL)
778
0
      goto error_return;
779
0
  }
780
781
0
      amt = symtab_hdr->sh_info;
782
0
      amt *= sizeof (asection *);
783
0
      sections = bfd_malloc (amt);
784
0
      if (sections == NULL && amt != 0)
785
0
  goto error_return;
786
787
0
      isymend = isymbuf + symtab_hdr->sh_info;
788
0
      for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
789
0
  {
790
0
    asection *isec;
791
792
0
    if (isym->st_shndx == SHN_UNDEF)
793
0
      isec = bfd_und_section_ptr;
794
0
    else if (isym->st_shndx == SHN_ABS)
795
0
      isec = bfd_abs_section_ptr;
796
0
    else if (isym->st_shndx == SHN_COMMON)
797
0
      isec = bfd_com_section_ptr;
798
0
    else
799
0
      isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
800
801
0
    *secpp = isec;
802
0
  }
803
804
0
      if (!elf32_crx_relocate_section (link_info, input_bfd,
805
0
               input_section, data, internal_relocs,
806
0
               isymbuf, sections))
807
0
  goto error_return;
808
809
0
      free (sections);
810
0
      if (symtab_hdr->contents != (unsigned char *) isymbuf)
811
0
  free (isymbuf);
812
0
      if (elf_section_data (input_section)->relocs != internal_relocs)
813
0
  free (internal_relocs);
814
0
    }
815
816
0
  return data;
817
818
0
 error_return:
819
0
  free (sections);
820
0
  if (symtab_hdr->contents != (unsigned char *) isymbuf)
821
0
    free (isymbuf);
822
0
  if (elf_section_data (input_section)->relocs != internal_relocs)
823
0
    free (internal_relocs);
824
0
  if (orig_data == NULL)
825
0
    free (data);
826
0
  return NULL;
827
0
}
828
829
/* Relocate a CRX ELF section.  */
830
831
static int
832
elf32_crx_relocate_section (struct bfd_link_info *info,
833
          bfd *input_bfd, asection *input_section,
834
          bfd_byte *contents, Elf_Internal_Rela *relocs,
835
          Elf_Internal_Sym *local_syms,
836
          asection **local_sections)
837
0
{
838
0
  Elf_Internal_Shdr *symtab_hdr;
839
0
  struct elf_link_hash_entry **sym_hashes;
840
0
  Elf_Internal_Rela *rel, *relend;
841
842
0
  symtab_hdr = &elf_symtab_hdr (input_bfd);
843
0
  sym_hashes = elf_sym_hashes (input_bfd);
844
845
0
  rel = relocs;
846
0
  relend = relocs + input_section->reloc_count;
847
0
  for (; rel < relend; rel++)
848
0
    {
849
0
      int r_type;
850
0
      reloc_howto_type *howto;
851
0
      unsigned long r_symndx;
852
0
      Elf_Internal_Sym *sym;
853
0
      asection *sec;
854
0
      struct elf_link_hash_entry *h;
855
0
      bfd_vma relocation;
856
0
      bfd_reloc_status_type r;
857
858
0
      r_symndx = ELF32_R_SYM (rel->r_info);
859
0
      r_type = ELF32_R_TYPE (rel->r_info);
860
0
      howto = crx_elf_howto_table + (r_type);
861
862
0
      h = NULL;
863
0
      sym = NULL;
864
0
      sec = NULL;
865
0
      if (r_symndx < symtab_hdr->sh_info)
866
0
  {
867
0
    sym = local_syms + r_symndx;
868
0
    sec = local_sections[r_symndx];
869
0
    relocation = _bfd_elf_rela_local_sym (info->output_bfd,
870
0
            sym, &sec, rel);
871
0
  }
872
0
      else
873
0
  {
874
0
    bool unresolved_reloc, warned, ignored;
875
876
0
    RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
877
0
           r_symndx, symtab_hdr, sym_hashes,
878
0
           h, sec, relocation,
879
0
           unresolved_reloc, warned, ignored);
880
0
  }
881
882
0
      if (sec != NULL && discarded_section (sec))
883
0
  RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
884
0
           rel, 1, relend, R_CRX_NONE,
885
0
           howto, 0, contents);
886
887
0
      if (bfd_link_relocatable (info))
888
0
  continue;
889
890
0
      r = crx_elf_final_link_relocate (howto, input_bfd, info->output_bfd,
891
0
               input_section,
892
0
               contents, rel->r_offset,
893
0
               relocation, rel->r_addend,
894
0
               info, sec, h == NULL);
895
896
0
      if (r != bfd_reloc_ok)
897
0
  {
898
0
    const char *name;
899
0
    const char *msg = (const char *) 0;
900
901
0
    if (h != NULL)
902
0
      name = h->root.root.string;
903
0
    else
904
0
      {
905
0
        name = (bfd_elf_string_from_elf_section
906
0
          (input_bfd, symtab_hdr->sh_link, sym->st_name));
907
0
        if (name == NULL || *name == '\0')
908
0
    name = bfd_section_name (sec);
909
0
      }
910
911
0
    switch (r)
912
0
      {
913
0
       case bfd_reloc_overflow:
914
0
         (*info->callbacks->reloc_overflow)
915
0
     (info, (h ? &h->root : NULL), name, howto->name,
916
0
      (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
917
0
         break;
918
919
0
       case bfd_reloc_undefined:
920
0
         (*info->callbacks->undefined_symbol)
921
0
     (info, name, input_bfd, input_section, rel->r_offset, true);
922
0
         break;
923
924
0
       case bfd_reloc_outofrange:
925
0
         msg = _("internal error: out of range error");
926
0
         goto common_error;
927
928
0
       case bfd_reloc_notsupported:
929
0
         msg = _("internal error: unsupported relocation error");
930
0
         goto common_error;
931
932
0
       case bfd_reloc_dangerous:
933
0
         msg = _("internal error: dangerous error");
934
0
         goto common_error;
935
936
0
       default:
937
0
         msg = _("internal error: unknown error");
938
         /* Fall through.  */
939
940
0
       common_error:
941
0
         (*info->callbacks->warning) (info, msg, name, input_bfd,
942
0
              input_section, rel->r_offset);
943
0
         break;
944
0
      }
945
0
  }
946
0
    }
947
948
0
  return true;
949
0
}
950
951
/* This function handles relaxing for the CRX.
952
953
   There's quite a few relaxing opportunites available on the CRX:
954
955
  * bal/bcond:32 -> bal/bcond:16           2 bytes
956
  * bcond:16 -> bcond:8            2 bytes
957
  * cmpbcond:24 -> cmpbcond:8          2 bytes
958
  * arithmetic imm32 -> arithmetic imm16         2 bytes
959
960
   Symbol- and reloc-reading infrastructure copied from elf-m10200.c.  */
961
962
static bool
963
elf32_crx_relax_section (bfd *abfd, asection *sec,
964
       struct bfd_link_info *link_info, bool *again)
965
0
{
966
0
  Elf_Internal_Shdr *symtab_hdr;
967
0
  Elf_Internal_Rela *internal_relocs;
968
0
  Elf_Internal_Rela *irel, *irelend;
969
0
  bfd_byte *contents = NULL;
970
0
  Elf_Internal_Sym *isymbuf = NULL;
971
972
  /* Assume nothing changes.  */
973
0
  *again = false;
974
975
  /* We don't have to do anything for a relocatable link, if
976
     this section does not have relocs, or if this is not a
977
     code section.  */
978
0
  if (bfd_link_relocatable (link_info)
979
0
      || sec->reloc_count == 0
980
0
      || (sec->flags & SEC_RELOC) == 0
981
0
      || (sec->flags & SEC_HAS_CONTENTS) == 0
982
0
      || (sec->flags & SEC_CODE) == 0)
983
0
    return true;
984
985
0
  symtab_hdr = &elf_symtab_hdr (abfd);
986
987
  /* Get a copy of the native relocations.  */
988
0
  internal_relocs = (_bfd_elf_link_read_relocs
989
0
         (abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
990
0
          link_info->keep_memory));
991
0
  if (internal_relocs == NULL)
992
0
    goto error_return;
993
994
  /* Walk through them looking for relaxing opportunities.  */
995
0
  irelend = internal_relocs + sec->reloc_count;
996
0
  for (irel = internal_relocs; irel < irelend; irel++)
997
0
    {
998
0
      bfd_vma symval;
999
1000
      /* If this isn't something that can be relaxed, then ignore
1001
   this reloc.  */
1002
0
      if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL32
1003
0
    && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL16
1004
0
    && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL24
1005
0
    && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_IMM32)
1006
0
  continue;
1007
1008
      /* Get the section contents if we haven't done so already.  */
1009
0
      if (contents == NULL)
1010
0
  {
1011
    /* Get cached copy if it exists.  */
1012
0
    if (elf_section_data (sec)->this_hdr.contents != NULL)
1013
0
      contents = elf_section_data (sec)->this_hdr.contents;
1014
    /* Go get them off disk.  */
1015
0
    else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
1016
0
      goto error_return;
1017
0
  }
1018
1019
      /* Read this BFD's local symbols if we haven't done so already.  */
1020
0
      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1021
0
  {
1022
0
    isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1023
0
    if (isymbuf == NULL)
1024
0
      isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1025
0
              symtab_hdr->sh_info, 0,
1026
0
              NULL, NULL, NULL);
1027
0
    if (isymbuf == NULL)
1028
0
      goto error_return;
1029
0
  }
1030
1031
      /* Get the value of the symbol referred to by the reloc.  */
1032
0
      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1033
0
  {
1034
    /* A local symbol.  */
1035
0
    Elf_Internal_Sym *isym;
1036
0
    asection *sym_sec;
1037
1038
0
    isym = isymbuf + ELF32_R_SYM (irel->r_info);
1039
0
    if (isym->st_shndx == SHN_UNDEF)
1040
0
      sym_sec = bfd_und_section_ptr;
1041
0
    else if (isym->st_shndx == SHN_ABS)
1042
0
      sym_sec = bfd_abs_section_ptr;
1043
0
    else if (isym->st_shndx == SHN_COMMON)
1044
0
      sym_sec = bfd_com_section_ptr;
1045
0
    else
1046
0
      sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1047
0
    symval = (isym->st_value
1048
0
        + sym_sec->output_section->vma
1049
0
        + sym_sec->output_offset);
1050
0
  }
1051
0
      else
1052
0
  {
1053
0
    unsigned long indx;
1054
0
    struct elf_link_hash_entry *h;
1055
1056
    /* An external symbol.  */
1057
0
    indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1058
0
    h = elf_sym_hashes (abfd)[indx];
1059
0
    BFD_ASSERT (h != NULL);
1060
1061
0
    if (h->root.type != bfd_link_hash_defined
1062
0
        && h->root.type != bfd_link_hash_defweak)
1063
      /* This appears to be a reference to an undefined
1064
         symbol.  Just ignore it--it will be caught by the
1065
         regular reloc processing.  */
1066
0
      continue;
1067
1068
0
    symval = (h->root.u.def.value
1069
0
        + h->root.u.def.section->output_section->vma
1070
0
        + h->root.u.def.section->output_offset);
1071
0
  }
1072
1073
      /* For simplicity of coding, we are going to modify the section
1074
   contents, the section relocs, and the BFD symbol table.  We
1075
   must tell the rest of the code not to free up this
1076
   information.  It would be possible to instead create a table
1077
   of changes which have to be made, as is done in coff-mips.c;
1078
   that would be more work, but would require less memory when
1079
   the linker is run.  */
1080
1081
      /* Try to turn a 32bit pc-relative branch/call into
1082
   a 16bit pc-relative branch/call.  */
1083
0
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL32)
1084
0
  {
1085
0
    bfd_vma value = symval;
1086
1087
    /* Deal with pc-relative gunk.  */
1088
0
    value -= (sec->output_section->vma + sec->output_offset);
1089
0
    value -= irel->r_offset;
1090
0
    value += irel->r_addend;
1091
1092
    /* See if the value will fit in 16 bits, note the high value is
1093
       0xfffe + 2 as the target will be two bytes closer if we are
1094
       able to relax.  */
1095
0
    if ((long) value < 0x10000 && (long) value > -0x10002)
1096
0
      {
1097
0
        unsigned short code;
1098
1099
        /* Get the opcode.  */
1100
0
        code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1101
1102
        /* Verify it's a 'bal'/'bcond' and fix the opcode.  */
1103
0
        if ((code & 0xfff0) == 0x3170)
1104
0
    bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1105
0
        else if ((code & 0xf0ff) == 0x707f)
1106
0
    bfd_put_8 (abfd, 0x7e, contents + irel->r_offset);
1107
0
        else
1108
0
    continue;
1109
1110
        /* Note that we've changed the relocs, section contents, etc.  */
1111
0
        elf_section_data (sec)->relocs = internal_relocs;
1112
0
        elf_section_data (sec)->this_hdr.contents = contents;
1113
0
        symtab_hdr->contents = (unsigned char *) isymbuf;
1114
1115
        /* Fix the relocation's type.  */
1116
0
        irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1117
0
             R_CRX_REL16);
1118
1119
        /* Delete two bytes of data.  */
1120
0
        if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1121
0
               irel->r_offset + 2, 2))
1122
0
    goto error_return;
1123
1124
        /* That will change things, so, we should relax again.
1125
     Note that this is not required, and it may be slow.  */
1126
0
        *again = true;
1127
0
      }
1128
0
  }
1129
1130
      /* Try to turn a 16bit pc-relative branch into an
1131
   8bit pc-relative branch.  */
1132
0
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL16)
1133
0
  {
1134
0
    bfd_vma value = symval;
1135
1136
    /* Deal with pc-relative gunk.  */
1137
0
    value -= (sec->output_section->vma + sec->output_offset);
1138
0
    value -= irel->r_offset;
1139
0
    value += irel->r_addend;
1140
1141
    /* See if the value will fit in 8 bits, note the high value is
1142
       0xfc + 2 as the target will be two bytes closer if we are
1143
       able to relax.  */
1144
0
    if ((long) value < 0xfe && (long) value > -0x100)
1145
0
      {
1146
0
        unsigned short code;
1147
1148
        /* Get the opcode.  */
1149
0
        code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1150
1151
        /* Verify it's a 'bcond' opcode.  */
1152
0
        if ((code & 0xf0ff) != 0x707e)
1153
0
    continue;
1154
1155
        /* Note that we've changed the relocs, section contents, etc.  */
1156
0
        elf_section_data (sec)->relocs = internal_relocs;
1157
0
        elf_section_data (sec)->this_hdr.contents = contents;
1158
0
        symtab_hdr->contents = (unsigned char *) isymbuf;
1159
1160
        /* Fix the relocation's type.  */
1161
0
        irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1162
0
             R_CRX_REL8);
1163
1164
        /* Delete two bytes of data.  */
1165
0
        if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1166
0
               irel->r_offset + 2, 2))
1167
0
    goto error_return;
1168
1169
        /* That will change things, so, we should relax again.
1170
     Note that this is not required, and it may be slow.  */
1171
0
        *again = true;
1172
0
      }
1173
0
  }
1174
1175
      /* Try to turn a 24bit pc-relative cmp&branch into
1176
   an 8bit pc-relative cmp&branch.  */
1177
0
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL24)
1178
0
  {
1179
0
    bfd_vma value = symval;
1180
1181
    /* Deal with pc-relative gunk.  */
1182
0
    value -= (sec->output_section->vma + sec->output_offset);
1183
0
    value -= irel->r_offset;
1184
0
    value += irel->r_addend;
1185
1186
    /* See if the value will fit in 8 bits, note the high value is
1187
       0x7e + 2 as the target will be two bytes closer if we are
1188
       able to relax.  */
1189
0
    if ((long) value < 0x100 && (long) value > -0x100)
1190
0
      {
1191
0
        unsigned short code;
1192
1193
        /* Get the opcode.  */
1194
0
        code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1195
1196
        /* Verify it's a 'cmp&branch' opcode.  */
1197
0
        if ((code & 0xfff0) != 0x3180 && (code & 0xfff0) != 0x3190
1198
0
         && (code & 0xfff0) != 0x31a0 && (code & 0xfff0) != 0x31c0
1199
0
         && (code & 0xfff0) != 0x31d0 && (code & 0xfff0) != 0x31e0
1200
         /* Or a Co-processor branch ('bcop').  */
1201
0
         && (code & 0xfff0) != 0x3010 && (code & 0xfff0) != 0x3110)
1202
0
    continue;
1203
1204
        /* Note that we've changed the relocs, section contents, etc.  */
1205
0
        elf_section_data (sec)->relocs = internal_relocs;
1206
0
        elf_section_data (sec)->this_hdr.contents = contents;
1207
0
        symtab_hdr->contents = (unsigned char *) isymbuf;
1208
1209
        /* Fix the opcode.  */
1210
0
        bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1);
1211
1212
        /* Fix the relocation's type.  */
1213
0
        irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1214
0
             R_CRX_REL8_CMP);
1215
1216
        /* Delete two bytes of data.  */
1217
0
        if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1218
0
               irel->r_offset + 4, 2))
1219
0
    goto error_return;
1220
1221
        /* That will change things, so, we should relax again.
1222
     Note that this is not required, and it may be slow.  */
1223
0
        *again = true;
1224
0
      }
1225
0
  }
1226
1227
      /* Try to turn a 32bit immediate address into
1228
   a 16bit immediate address.  */
1229
0
      if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_IMM32)
1230
0
  {
1231
0
    bfd_vma value = symval;
1232
1233
    /* See if the value will fit in 16 bits.  */
1234
0
    if ((long) value < 0x7fff && (long) value > -0x8000)
1235
0
      {
1236
0
        unsigned short code;
1237
1238
        /* Get the opcode.  */
1239
0
        code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1240
1241
        /* Verify it's a 'arithmetic double'.  */
1242
0
        if ((code & 0xf0f0) != 0x20f0)
1243
0
    continue;
1244
1245
        /* Note that we've changed the relocs, section contents, etc.  */
1246
0
        elf_section_data (sec)->relocs = internal_relocs;
1247
0
        elf_section_data (sec)->this_hdr.contents = contents;
1248
0
        symtab_hdr->contents = (unsigned char *) isymbuf;
1249
1250
        /* Fix the opcode.  */
1251
0
        bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
1252
1253
        /* Fix the relocation's type.  */
1254
0
        irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1255
0
             R_CRX_IMM16);
1256
1257
        /* Delete two bytes of data.  */
1258
0
        if (!elf32_crx_relax_delete_bytes (link_info, abfd, sec,
1259
0
               irel->r_offset + 2, 2))
1260
0
    goto error_return;
1261
1262
        /* That will change things, so, we should relax again.
1263
     Note that this is not required, and it may be slow.  */
1264
0
        *again = true;
1265
0
      }
1266
0
  }
1267
0
    }
1268
1269
0
  if (isymbuf != NULL
1270
0
      && symtab_hdr->contents != (unsigned char *) isymbuf)
1271
0
    {
1272
0
      if (! link_info->keep_memory)
1273
0
  free (isymbuf);
1274
0
      else
1275
0
  {
1276
    /* Cache the symbols for elf_link_input_bfd.  */
1277
0
    symtab_hdr->contents = (unsigned char *) isymbuf;
1278
0
  }
1279
0
    }
1280
1281
0
  if (contents != NULL
1282
0
      && elf_section_data (sec)->this_hdr.contents != contents)
1283
0
    {
1284
0
      if (! link_info->keep_memory)
1285
0
  free (contents);
1286
0
      else
1287
0
  {
1288
    /* Cache the section contents for elf_link_input_bfd.  */
1289
0
    elf_section_data (sec)->this_hdr.contents = contents;
1290
0
  }
1291
0
    }
1292
1293
0
  if (elf_section_data (sec)->relocs != internal_relocs)
1294
0
    free (internal_relocs);
1295
1296
0
  return true;
1297
1298
0
 error_return:
1299
0
  if (symtab_hdr->contents != (unsigned char *) isymbuf)
1300
0
    free (isymbuf);
1301
0
  if (elf_section_data (sec)->this_hdr.contents != contents)
1302
0
    free (contents);
1303
0
  if (elf_section_data (sec)->relocs != internal_relocs)
1304
0
    free (internal_relocs);
1305
1306
  return false;
1307
0
}
1308
1309
/* Definitions for setting CRX target vector.  */
1310
#define TARGET_LITTLE_SYM   crx_elf32_vec
1311
#define TARGET_LITTLE_NAME    "elf32-crx"
1312
#define ELF_ARCH      bfd_arch_crx
1313
#define ELF_MACHINE_CODE    EM_CRX
1314
#define ELF_MAXPAGESIZE     0x1
1315
#define elf_symbol_leading_char   '_'
1316
1317
#define bfd_elf32_bfd_reloc_type_lookup elf_crx_reloc_type_lookup
1318
#define bfd_elf32_bfd_reloc_name_lookup \
1319
          elf_crx_reloc_name_lookup
1320
#define elf_info_to_howto   elf_crx_info_to_howto
1321
#define elf_info_to_howto_rel   NULL
1322
#define elf_backend_relocate_section  elf32_crx_relocate_section
1323
#define bfd_elf32_bfd_relax_section elf32_crx_relax_section
1324
#define bfd_elf32_bfd_get_relocated_section_contents \
1325
        elf32_crx_get_relocated_section_contents
1326
#define elf_backend_can_gc_sections     1
1327
#define elf_backend_rela_normal   1
1328
1329
#include "elf32-target.h"