1 /* BFD back-end for National Semiconductor's CR16C ELF
2 Copyright (C) 2004-2018 Free Software Foundation, Inc.
4 This file is part of BFD, the Binary File Descriptor library.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
25 #include "elf/cr16c.h"
29 #define USE_REL 1 /* CR16C uses REL relocations instead of RELA. */
31 /* The following definition is based on EMPTY_HOWTO macro,
32 but also initiates the "name" field in HOWTO struct. */
33 #define ONLY_NAME_HOWTO(C) \
34 HOWTO ((C), 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, \
35 STRINGX(C), FALSE, 0, 0, FALSE)
37 /* reloc_map_index array maps CRASM relocation type into a BFD
38 relocation enum. The array's indices are synchronized with
39 RINDEX_16C_* indices, created in include/elf/cr16c.h.
41 1. elf32-cr16c.c : elf_cr16c_reloc_type_lookup().
42 2. asreloc.c : find_reloc_type(). */
44 RELOC_MAP reloc_map_index
[RINDEX_16C_MAX
] =
46 {R_16C_NUM08
, BFD_RELOC_16C_NUM08
},
47 {R_16C_NUM08_C
, BFD_RELOC_16C_NUM08_C
},
48 {R_16C_NUM16
, BFD_RELOC_16C_NUM16
},
49 {R_16C_NUM16_C
, BFD_RELOC_16C_NUM16_C
},
50 {R_16C_NUM32
, BFD_RELOC_16C_NUM32
},
51 {R_16C_NUM32_C
, BFD_RELOC_16C_NUM32_C
},
52 {R_16C_DISP04
, BFD_RELOC_16C_DISP04
},
53 {R_16C_DISP04_C
, BFD_RELOC_16C_DISP04_C
},
54 {R_16C_DISP08
, BFD_RELOC_16C_DISP08
},
55 {R_16C_DISP08_C
, BFD_RELOC_16C_DISP08_C
},
56 {R_16C_DISP16
, BFD_RELOC_16C_DISP16
},
57 {R_16C_DISP16_C
, BFD_RELOC_16C_DISP16_C
},
58 {R_16C_DISP24
, BFD_RELOC_16C_DISP24
},
59 {R_16C_DISP24_C
, BFD_RELOC_16C_DISP24_C
},
60 {R_16C_DISP24a
, BFD_RELOC_16C_DISP24a
},
61 {R_16C_DISP24a_C
, BFD_RELOC_16C_DISP24a_C
},
62 {R_16C_REG04
, BFD_RELOC_16C_REG04
},
63 {R_16C_REG04_C
, BFD_RELOC_16C_REG04_C
},
64 {R_16C_REG04a
, BFD_RELOC_16C_REG04a
},
65 {R_16C_REG04a_C
, BFD_RELOC_16C_REG04a_C
},
66 {R_16C_REG14
, BFD_RELOC_16C_REG14
},
67 {R_16C_REG14_C
, BFD_RELOC_16C_REG14_C
},
68 {R_16C_REG16
, BFD_RELOC_16C_REG16
},
69 {R_16C_REG16_C
, BFD_RELOC_16C_REG16_C
},
70 {R_16C_REG20
, BFD_RELOC_16C_REG20
},
71 {R_16C_REG20_C
, BFD_RELOC_16C_REG20_C
},
72 {R_16C_ABS20
, BFD_RELOC_16C_ABS20
},
73 {R_16C_ABS20_C
, BFD_RELOC_16C_ABS20_C
},
74 {R_16C_ABS24
, BFD_RELOC_16C_ABS24
},
75 {R_16C_ABS24_C
, BFD_RELOC_16C_ABS24_C
},
76 {R_16C_IMM04
, BFD_RELOC_16C_IMM04
},
77 {R_16C_IMM04_C
, BFD_RELOC_16C_IMM04_C
},
78 {R_16C_IMM16
, BFD_RELOC_16C_IMM16
},
79 {R_16C_IMM16_C
, BFD_RELOC_16C_IMM16_C
},
80 {R_16C_IMM20
, BFD_RELOC_16C_IMM20
},
81 {R_16C_IMM20_C
, BFD_RELOC_16C_IMM20_C
},
82 {R_16C_IMM24
, BFD_RELOC_16C_IMM24
},
83 {R_16C_IMM24_C
, BFD_RELOC_16C_IMM24_C
},
84 {R_16C_IMM32
, BFD_RELOC_16C_IMM32
},
85 {R_16C_IMM32_C
, BFD_RELOC_16C_IMM32_C
}
88 static reloc_howto_type elf_howto_table
[] =
90 /* 00 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM08
),
91 /* 01 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM08_C
),
92 /* 02 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM16
),
93 /* 03 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM16_C
),
94 /* 04 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM32
),
95 /* 05 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM32_C
),
96 /* 06 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP04
),
97 /* 07 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP04_C
),
98 /* 08 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP08
),
99 /* 09 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP08_C
),
100 /* 10 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP16
),
101 /* 11 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP16_C
),
102 /* 12 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24
),
103 /* 13 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24_C
),
104 /* 14 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24a
),
105 /* 15 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24a_C
),
106 /* 16 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04
),
107 /* 17 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04_C
),
108 /* 18 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04a
),
109 /* 19 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04a_C
),
110 /* 20 */ ONLY_NAME_HOWTO (RINDEX_16C_REG14
),
111 /* 21 */ ONLY_NAME_HOWTO (RINDEX_16C_REG14_C
),
112 /* 22 */ ONLY_NAME_HOWTO (RINDEX_16C_REG16
),
113 /* 23 */ ONLY_NAME_HOWTO (RINDEX_16C_REG16_C
),
114 /* 24 */ ONLY_NAME_HOWTO (RINDEX_16C_REG20
),
115 /* 25 */ ONLY_NAME_HOWTO (RINDEX_16C_REG20_C
),
116 /* 26 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS20
),
117 /* 27 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS20_C
),
118 /* 28 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS24
),
119 /* 29 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS24_C
),
120 /* 30 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM04
),
121 /* 31 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM04_C
),
122 /* 32 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM16
),
123 /* 33 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM16_C
),
124 /* 34 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM20
),
125 /* 35 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM20_C
),
126 /* 36 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM24
),
127 /* 37 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM24_C
),
128 /* 38 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM32
),
129 /* 39 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM32_C
)
133 /* Code to turn a code_type into a howto ptr, uses the above howto table. */
135 static reloc_howto_type
*
136 elf_cr16c_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
137 bfd_reloc_code_real_type code
)
141 for (i
= 0; i
< RINDEX_16C_MAX
; i
++)
143 if (code
== reloc_map_index
[i
].bfd_reloc_enum
)
145 /* printf ("CR16C Relocation Type is - %x\n", code); */
146 return & elf_howto_table
[i
];
150 /* printf ("This relocation Type is not supported - %x\n", code); */
154 static reloc_howto_type
*
155 elf_cr16c_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
160 for (i
= 0; i
< sizeof (elf_howto_table
) / sizeof (elf_howto_table
[0]); i
++)
161 if (elf_howto_table
[i
].name
!= NULL
162 && strcasecmp (elf_howto_table
[i
].name
, r_name
) == 0)
163 return &elf_howto_table
[i
];
169 elf_cr16c_info_to_howto (bfd
*abfd ATTRIBUTE_UNUSED
,
170 arelent
*cache_ptr ATTRIBUTE_UNUSED
,
171 Elf_Internal_Rela
*dst ATTRIBUTE_UNUSED
)
177 elf_cr16c_info_to_howto_rel (bfd
*abfd ATTRIBUTE_UNUSED
,
179 Elf_Internal_Rela
*dst
)
181 unsigned int r_type
= ELF32_R_TYPE (dst
->r_info
);
183 if (r_type
>= RINDEX_16C_MAX
)
185 /* xgettext:c-format */
186 _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
188 bfd_set_error (bfd_error_bad_value
);
191 cache_ptr
->howto
= &elf_howto_table
[r_type
];
195 /* Perform a relocation as part of a final link. */
197 static bfd_reloc_status_type
198 cr16c_elf_final_link_relocate (reloc_howto_type
*howto
,
200 bfd
*output_bfd ATTRIBUTE_UNUSED
,
201 asection
*input_section
,
205 bfd_vma addend ATTRIBUTE_UNUSED
,
206 struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
207 asection
*sym_sec ATTRIBUTE_UNUSED
,
208 int is_local ATTRIBUTE_UNUSED
)
211 short sword
; /* Extracted from the hole and put back. */
212 unsigned long format
, addr_type
, code_factor
;
214 unsigned short r_type
;
216 unsigned long disp20_opcod
;
221 long plus_factor
= 0; /* To be added to the hole. */
223 #define MIN_BYTE ((int) 0xFFFFFF80)
224 #define MIN_WORD ((int) 0xFFFF8000)
225 #define MAX_UWORD ((unsigned) 0x0000FFFF)
226 #define MAX_UBYTE ((unsigned) 0x000000FF)
228 r_type
= reloc_map_index
[howto
->type
].cr_reloc_type
;
229 format
= r_type
& R_FORMAT
;
230 size
= r_type
& R_SIZESP
;
231 addr_type
= r_type
& R_ADDRTYPE
;
232 code_factor
= ((addr_type
== R_CODE_ADDR
) ? 1 : 0);
239 case R_S_16C_08
: /* One byte. */
240 value
= bfd_get_8 (abfd
, (char *) data
+ octets
);
242 case R_S_16C_16
: /* Two bytes. */
243 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
246 case R_S_16C_32
: /* Four bytes. */
247 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
250 return bfd_reloc_notsupported
;
257 case R_S_16C_04
: /* word1(4-7). */
258 value
= bfd_get_8 (abfd
, (char *) data
+ octets
);
259 left_val
= value
& 0xF;
260 value
= (value
& 0xF0) >> 4;
264 case R_S_16C_08
: /* word1(0-3,8-11). */
265 sword
= bfd_get_16 (abfd
, (char *) data
+ octets
);
266 value
= sword
& 0x000F;
267 value
|= ((sword
& 0x0F00) >> 4);
268 left_val
= sword
& 0xF0F0;
273 case R_S_16C_16
: /* word2. */
274 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
276 value
= ((value
& 0xFFFE) >> 1) | ((value
& 0x1) << 15);
281 case R_S_16C_24_a
: /* word1(0-7),word2. */
282 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
283 left_val
= value
& 0x0000FF00;
284 value
= ((value
& 0xFFFE0000) >> 17) |
285 ((value
& 0x00010000) << 7) | ((value
& 0x000000FF) << 15);
287 if (value
& 0x1000000)
290 case R_S_16C_24
: /* word2(0-3,8-11),word3. */
291 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
292 left_val
= value
& 0x0000F0F0;
293 value
= ((value
>> 16) & 0x0000FFFF) |
294 ((value
& 0x00000F00) << 8) | ((value
& 0x0000000F) << 20);
296 value
= ((value
& 0x00FFFFFE) >> 1) | ((value
& 0x00000001) << 23);
299 if (value
& 0x1000000)
303 return bfd_reloc_notsupported
;
310 case R_S_16C_04
: /* word1(12-15) not scaled. */
311 value
= bfd_get_8 (abfd
, (char *) data
+ octets
);
312 left_val
= value
& 0xF0;
315 case R_S_16C_04_a
: /* word1(12-15) scaled by 2. */
316 value
= bfd_get_8 (abfd
, (char *) data
+ octets
);
317 left_val
= value
& 0xF0;
321 case R_S_16C_14
: /* word1(4-5),word2(0-3,8-15). */
322 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
323 left_val
= value
& 0x00F0FFCF;
324 value
= ((value
& 0xc0000000) >> 24) |
325 ((value
& 0x3F000000) >> 16) |
326 ((value
& 0x000F0000) >> 16) | (value
& 0x00000030);
328 case R_S_16C_16
: /* word2. */
329 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
332 case R_S_16C_20
: /* word2(8-11),word3. */
333 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
334 left_val
= value
& 0xF0;
335 value
= (value
& 0xF) << 16;
336 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
+ 1);
337 value
= value
| (unsigned short) sword
;
338 disp20_opcod
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
- 3);
339 disp20_opcod
|= 0x0FFF0000;
340 if ((disp20_opcod
== 0x4FFF0018) || /* loadb -disp20(reg) */
341 (disp20_opcod
== 0x5FFF0018) || /* loadb -disp20(rp) */
342 (disp20_opcod
== 0x8FFF0018) || /* loadd -disp20(reg) */
343 (disp20_opcod
== 0x9FFF0018) || /* loadd -disp20(rp) */
344 (disp20_opcod
== 0xCFFF0018) || /* loadw -disp20(reg) */
345 (disp20_opcod
== 0xDFFF0018) || /* loadw -disp20(rp) */
346 (disp20_opcod
== 0x4FFF0019) || /* storb -disp20(reg) */
347 (disp20_opcod
== 0x5FFF0019) || /* storb -disp20(rp) */
348 (disp20_opcod
== 0x8FFF0019) || /* stord -disp20(reg) */
349 (disp20_opcod
== 0x9FFF0019) || /* stord -disp20(rp) */
350 (disp20_opcod
== 0xCFFF0019) || /* storw -disp20(reg) */
351 (disp20_opcod
== 0xDFFF0019))
352 { /* storw -disp20(rp). */
359 return bfd_reloc_notsupported
;
366 case R_S_16C_20
: /* word1(0-3),word2. */
367 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
368 left_val
= value
& 0x0000FFF0;
369 value
= ((value
& 0xFFFF0000) >> 16) |
370 ((value
& 0x0000000F) << 16);
372 case R_S_16C_24
: /* word2(0-3,8-11),word3. */
373 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
374 left_val
= value
& 0x0000F0F0;
375 value
= ((value
& 0xFFFF0000) >> 16) |
376 ((value
& 0x00000F00) << 8) | ((value
& 0x0000000F) << 20);
379 return bfd_reloc_notsupported
;
386 case R_S_16C_04
: /* word1/2(4-7). */
387 value
= bfd_get_8 (abfd
, (char *) data
+ octets
);
388 left_val
= value
& 0xF;
389 value
= (value
& 0xF0) >> 4;
391 case R_S_16C_16
: /* word2. */
392 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
395 case R_S_16C_20
: /* word1(0-3),word2. */
396 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
397 left_val
= value
& 0x0000FFF0;
398 value
= ((value
& 0xFFFF0000) >> 16) |
399 ((value
& 0x0000000F) << 16);
401 case R_S_16C_32
: /* word2, word3. */
402 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
403 value
= ((value
& 0x0000FFFF) << 16) |
404 ((value
& 0xFFFF0000) >> 16);
407 return bfd_reloc_notsupported
;
411 return bfd_reloc_notsupported
;
414 switch ((r_type
& R_RELTO
) >> 4)
418 plus_factor
= Rvalue
;
420 case 1: /* R_PCREL. */
421 plus_factor
= Rvalue
-
422 (input_section
->output_section
->vma
+ input_section
->output_offset
);
425 return bfd_reloc_notsupported
;
430 if (plus_factor
>= -value
)
432 /* We need to change load/stor with negative
433 displ opcode to positive disp opcode (CR16C). */
436 value
= value
+ (plus_factor
>> code_factor
);
443 case R_S_16C_08
: /* One byte. */
444 if (value
> (int) MAX_UBYTE
|| value
< MIN_BYTE
)
445 return bfd_reloc_overflow
;
447 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
450 case R_S_16C_16
: /* Two bytes. */
451 if (value
> (int) MAX_UWORD
|| value
< MIN_WORD
)
452 return bfd_reloc_overflow
;
455 bfd_put_16 (abfd
, (bfd_vma
) sword
,
456 (unsigned char *) data
+ octets
);
459 case R_S_16C_32
: /* Four bytes. */
461 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
465 return bfd_reloc_notsupported
;
472 case R_S_16C_04
: /* word1(4-7). */
473 if ((value
- 32) > 32 || value
< 2)
474 return bfd_reloc_overflow
;
480 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
483 case R_S_16C_08
: /* word1(0-3,8-11). */
484 if (value
> 255 || value
< -256 || value
== 0x80)
485 return bfd_reloc_overflow
;
488 sword
= value
& 0x000F;
489 sword
|= (value
& 0x00F0) << 4;
491 bfd_put_16 (abfd
, (bfd_vma
) sword
,
492 (unsigned char *) data
+ octets
);
495 case R_S_16C_16
: /* word2. */
496 if (value
> 65535 || value
< -65536)
497 return bfd_reloc_overflow
;
500 value
= ((value
& 0x8000) >> 15) | ((value
& 0x7FFF) << 1);
502 bfd_put_16 (abfd
, (bfd_vma
) sword
,
503 (unsigned char *) data
+ octets
);
506 case R_S_16C_24_a
: /* word1(0-7),word2. */
507 if (value
> 16777215 || value
< -16777216)
508 return bfd_reloc_overflow
;
511 value
= ((value
& 0x00007FFF) << 17) |
512 ((value
& 0x00800000) >> 7) | ((value
& 0x007F8000) >> 15);
514 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
517 case R_S_16C_24
: /* word2(0-3,8-11),word3. */
518 if (value
> 16777215 || value
< -16777216)
519 return bfd_reloc_overflow
;
523 value
= ((value
& 0x007FFFFF) << 1) | ((value
& 0x00800000) >> 23);
525 value
= ((value
& 0x0000FFFF) << 16) |
526 ((value
& 0x000F0000) >> 8) | ((value
& 0x00F00000) >> 20);
528 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
532 return bfd_reloc_notsupported
;
539 case R_S_16C_04
: /* word1(12-15) not scaled. */
540 if (value
> 13 || value
< 0)
541 return bfd_reloc_overflow
;
544 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
547 case R_S_16C_04_a
: /* word1(12-15) not scaled. */
548 if (value
> 26 || value
< 0)
549 return bfd_reloc_overflow
;
553 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
556 case R_S_16C_14
: /* word1(4-5),word2(0-3,8-15). */
557 if (value
< 0 || value
> 16383)
558 return bfd_reloc_overflow
;
560 value
= ((value
& 0x000000c0) << 24) |
561 ((value
& 0x00003F00) << 16) |
562 ((value
& 0x0000000F) << 16) | (value
& 0x00000030);
564 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
567 case R_S_16C_16
: /* word2. */
568 if (value
> 65535 || value
< 0)
569 return bfd_reloc_overflow
;
572 bfd_put_16 (abfd
, (bfd_vma
) sword
,
573 (unsigned char *) data
+ octets
);
576 case R_S_16C_20
: /* word2(8-11),word3. */
577 /* if (value > 1048575 || value < 0) RELOC_ERROR(1); */
579 sword
= value
& 0x0000FFFF;
580 value
= (value
& 0x000F0000) >> 16;
582 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
583 bfd_put_16 (abfd
, (bfd_vma
) sword
,
584 (unsigned char *) data
+ octets
+ 1);
587 /* Change load/stor negative displ opcode
588 to load/stor positive displ opcode. */
589 value
= bfd_get_8 (abfd
, (char *) data
+ octets
- 3);
592 bfd_put_8 (abfd
, (bfd_vma
) value
,
593 (unsigned char *) data
+ octets
- 3);
598 return bfd_reloc_notsupported
;
605 case R_S_16C_20
: /* word1(0-3),word2. */
606 if (value
> 1048575 || value
< 0)
607 return bfd_reloc_overflow
;
609 value
= ((value
& 0x0000FFFF) << 16) |
610 ((value
& 0x000F0000) >> 16);
612 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
615 case R_S_16C_24
: /* word2(0-3,8-11),word3. */
616 /* if (value > 16777215 || value < 0) RELOC_ERROR(1); */
618 value
= ((value
& 0x0000FFFF) << 16) |
619 ((value
& 0x000F0000) >> 8) | ((value
& 0x00F00000) >> 20);
621 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
625 return bfd_reloc_notsupported
;
632 case R_S_16C_04
: /* word1/2(4-7). */
633 if (value
> 15 || value
< -1)
634 return bfd_reloc_overflow
;
638 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
641 case R_S_16C_16
: /* word2. */
642 if (value
> 32767 || value
< -32768)
643 return bfd_reloc_overflow
;
646 bfd_put_16 (abfd
, (bfd_vma
) sword
,
647 (unsigned char *) data
+ octets
);
650 case R_S_16C_20
: /* word1(0-3),word2. */
651 if (value
> 1048575 || value
< 0)
652 return bfd_reloc_overflow
;
654 value
= ((value
& 0x0000FFFF) << 16) |
655 ((value
& 0x000F0000) >> 16);
657 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
660 case R_S_16C_32
: /* word2, word3. */
662 value
= ((value
& 0x0000FFFF) << 16) |
663 ((value
& 0xFFFF0000) >> 16);
664 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
668 return bfd_reloc_notsupported
;
672 return bfd_reloc_notsupported
;
678 /* Relocate a CR16C ELF section. */
681 elf32_cr16c_relocate_section (bfd
*output_bfd
,
682 struct bfd_link_info
*info
,
684 asection
*input_section
,
686 Elf_Internal_Rela
*relocs
,
687 Elf_Internal_Sym
*local_syms
,
688 asection
**local_sections
)
690 Elf_Internal_Shdr
*symtab_hdr
;
691 struct elf_link_hash_entry
**sym_hashes
;
692 Elf_Internal_Rela
*rel
, *relend
;
694 symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
695 sym_hashes
= elf_sym_hashes (input_bfd
);
698 relend
= relocs
+ input_section
->reloc_count
;
699 for (; rel
< relend
; rel
++)
702 reloc_howto_type
*howto
;
703 unsigned long r_symndx
;
704 Elf_Internal_Sym
*sym
;
706 struct elf_link_hash_entry
*h
;
708 bfd_reloc_status_type r
;
710 r_symndx
= ELF32_R_SYM (rel
->r_info
);
711 r_type
= ELF32_R_TYPE (rel
->r_info
);
712 howto
= elf_howto_table
+ r_type
;
717 if (r_symndx
< symtab_hdr
->sh_info
)
719 sym
= local_syms
+ r_symndx
;
720 sec
= local_sections
[r_symndx
];
721 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
725 bfd_boolean unresolved_reloc
, warned
, ignored
;
727 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
728 r_symndx
, symtab_hdr
, sym_hashes
,
730 unresolved_reloc
, warned
, ignored
);
733 if (sec
!= NULL
&& discarded_section (sec
))
734 RELOC_AGAINST_DISCARDED_SECTION (info
, input_bfd
, input_section
,
735 rel
, 1, relend
, howto
, 0, contents
);
737 if (bfd_link_relocatable (info
))
739 /* This is a relocatable link. We don't have to change
740 anything, unless the reloc is against a section symbol,
741 in which case we have to adjust according to where the
742 section symbol winds up in the output section. */
743 if (sym
!= NULL
&& ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
744 rel
->r_addend
+= sec
->output_offset
;
748 r
= cr16c_elf_final_link_relocate (howto
, input_bfd
, output_bfd
,
750 contents
, rel
->r_offset
,
751 relocation
, rel
->r_addend
,
752 info
, sec
, h
== NULL
);
754 if (r
!= bfd_reloc_ok
)
757 const char *msg
= (const char *) 0;
760 name
= h
->root
.root
.string
;
763 name
= (bfd_elf_string_from_elf_section
764 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
));
765 if (name
== NULL
|| *name
== '\0')
766 name
= bfd_section_name (input_bfd
, sec
);
771 case bfd_reloc_overflow
:
772 (*info
->callbacks
->reloc_overflow
)
773 (info
, (h
? &h
->root
: NULL
), name
, howto
->name
,
774 (bfd_vma
) 0, input_bfd
, input_section
, rel
->r_offset
);
777 case bfd_reloc_undefined
:
778 (*info
->callbacks
->undefined_symbol
)
779 (info
, name
, input_bfd
, input_section
, rel
->r_offset
, TRUE
);
782 case bfd_reloc_outofrange
:
783 msg
= _("internal error: out of range error");
786 case bfd_reloc_notsupported
:
787 msg
= _("internal error: unsupported relocation error");
790 case bfd_reloc_dangerous
:
791 msg
= _("internal error: dangerous error");
795 msg
= _("internal error: unknown error");
799 (*info
->callbacks
->warning
) (info
, msg
, name
, input_bfd
,
800 input_section
, rel
->r_offset
);
809 /* CR16C ELF uses three common sections:
810 One is for default common symbols (placed in usual common section).
811 Second is for near common symbols (placed in "ncommon" section).
812 Third is for far common symbols (placed in "fcommon" section).
813 The following implementation is based on elf32-mips architecture */
815 static asection cr16c_elf_fcom_section
;
816 static asymbol cr16c_elf_fcom_symbol
;
817 static asymbol
* cr16c_elf_fcom_symbol_ptr
;
818 static asection cr16c_elf_ncom_section
;
819 static asymbol cr16c_elf_ncom_symbol
;
820 static asymbol
* cr16c_elf_ncom_symbol_ptr
;
822 /* Given a BFD section, try to locate the
823 corresponding ELF section index. */
826 elf32_cr16c_section_from_bfd_section (bfd
*abfd ATTRIBUTE_UNUSED
,
830 if (strcmp (bfd_get_section_name (abfd
, sec
), ".fcommon") == 0)
831 *retval
= SHN_CR16C_FCOMMON
;
832 else if (strcmp (bfd_get_section_name (abfd
, sec
), ".ncommon") == 0)
833 *retval
= SHN_CR16C_NCOMMON
;
840 /* Handle the special CR16C section numbers that a symbol may use. */
843 elf32_cr16c_symbol_processing (bfd
*abfd ATTRIBUTE_UNUSED
,
846 elf_symbol_type
*elfsym
= (elf_symbol_type
*) asym
;
849 indx
= elfsym
->internal_elf_sym
.st_shndx
;
853 case SHN_CR16C_FCOMMON
:
854 if (cr16c_elf_fcom_section
.name
== NULL
)
856 /* Initialize the far common section. */
857 cr16c_elf_fcom_section
.name
= ".fcommon";
858 cr16c_elf_fcom_section
.flags
= SEC_IS_COMMON
| SEC_ALLOC
;
859 cr16c_elf_fcom_section
.output_section
= &cr16c_elf_fcom_section
;
860 cr16c_elf_fcom_section
.symbol
= &cr16c_elf_fcom_symbol
;
861 cr16c_elf_fcom_section
.symbol_ptr_ptr
= &cr16c_elf_fcom_symbol_ptr
;
862 cr16c_elf_fcom_symbol
.name
= ".fcommon";
863 cr16c_elf_fcom_symbol
.flags
= BSF_SECTION_SYM
;
864 cr16c_elf_fcom_symbol
.section
= &cr16c_elf_fcom_section
;
865 cr16c_elf_fcom_symbol_ptr
= &cr16c_elf_fcom_symbol
;
867 asym
->section
= &cr16c_elf_fcom_section
;
868 asym
->value
= elfsym
->internal_elf_sym
.st_size
;
870 case SHN_CR16C_NCOMMON
:
871 if (cr16c_elf_ncom_section
.name
== NULL
)
873 /* Initialize the far common section. */
874 cr16c_elf_ncom_section
.name
= ".ncommon";
875 cr16c_elf_ncom_section
.flags
= SEC_IS_COMMON
| SEC_ALLOC
;
876 cr16c_elf_ncom_section
.output_section
= &cr16c_elf_ncom_section
;
877 cr16c_elf_ncom_section
.symbol
= &cr16c_elf_ncom_symbol
;
878 cr16c_elf_ncom_section
.symbol_ptr_ptr
= &cr16c_elf_ncom_symbol_ptr
;
879 cr16c_elf_ncom_symbol
.name
= ".ncommon";
880 cr16c_elf_ncom_symbol
.flags
= BSF_SECTION_SYM
;
881 cr16c_elf_ncom_symbol
.section
= &cr16c_elf_ncom_section
;
882 cr16c_elf_ncom_symbol_ptr
= &cr16c_elf_ncom_symbol
;
884 asym
->section
= &cr16c_elf_ncom_section
;
885 asym
->value
= elfsym
->internal_elf_sym
.st_size
;
890 /* Hook called by the linker routine which adds symbols from an object
891 file. We must handle the special cr16c section numbers here. */
894 elf32_cr16c_add_symbol_hook (bfd
*abfd
,
895 struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
896 Elf_Internal_Sym
*sym
,
897 const char **namep ATTRIBUTE_UNUSED
,
898 flagword
*flagsp ATTRIBUTE_UNUSED
,
902 unsigned int indx
= sym
->st_shndx
;
906 case SHN_CR16C_FCOMMON
:
907 *secp
= bfd_make_section_old_way (abfd
, ".fcommon");
908 (*secp
)->flags
|= SEC_IS_COMMON
;
909 *valp
= sym
->st_size
;
911 case SHN_CR16C_NCOMMON
:
912 *secp
= bfd_make_section_old_way (abfd
, ".ncommon");
913 (*secp
)->flags
|= SEC_IS_COMMON
;
914 *valp
= sym
->st_size
;
922 elf32_cr16c_link_output_symbol_hook (struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
923 const char *name ATTRIBUTE_UNUSED
,
924 Elf_Internal_Sym
*sym
,
926 struct elf_link_hash_entry
*h ATTRIBUTE_UNUSED
)
928 /* If we see a common symbol, which implies a relocatable link, then
929 if a symbol was in a special common section in an input file, mark
930 it as a special common in the output file. */
932 if (sym
->st_shndx
== SHN_COMMON
)
934 if (strcmp (input_sec
->name
, ".fcommon") == 0)
935 sym
->st_shndx
= SHN_CR16C_FCOMMON
;
936 else if (strcmp (input_sec
->name
, ".ncommon") == 0)
937 sym
->st_shndx
= SHN_CR16C_NCOMMON
;
943 /* Definitions for setting CR16C target vector. */
944 #define TARGET_LITTLE_SYM cr16c_elf32_vec
945 #define TARGET_LITTLE_NAME "elf32-cr16c"
946 #define ELF_ARCH bfd_arch_cr16c
947 #define ELF_MACHINE_CODE EM_CR
948 #define ELF_MAXPAGESIZE 0x1
949 #define elf_symbol_leading_char '_'
951 #define bfd_elf32_bfd_reloc_type_lookup elf_cr16c_reloc_type_lookup
952 #define bfd_elf32_bfd_reloc_name_lookup elf_cr16c_reloc_name_lookup
953 #define elf_info_to_howto elf_cr16c_info_to_howto
954 #define elf_info_to_howto_rel elf_cr16c_info_to_howto_rel
955 #define elf_backend_relocate_section elf32_cr16c_relocate_section
956 #define elf_backend_symbol_processing elf32_cr16c_symbol_processing
957 #define elf_backend_section_from_bfd_section elf32_cr16c_section_from_bfd_section
958 #define elf_backend_add_symbol_hook elf32_cr16c_add_symbol_hook
959 #define elf_backend_link_output_symbol_hook elf32_cr16c_link_output_symbol_hook
961 #define elf_backend_can_gc_sections 1
963 #include "elf32-target.h"