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