Coverage Report

Created: 2026-03-10 08:46

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