Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / elf32-xc16x.c
CommitLineData
d70c5fc7 1/* Infineon XC16X-specific support for 16-bit ELF.
219d1afa 2 Copyright (C) 2006-2018 Free Software Foundation, Inc.
68ffbac6 3 Contributed by KPIT Cummins Infosystems
d70c5fc7
NC
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
d70c5fc7
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, 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
d70c5fc7 21
d70c5fc7 22#include "sysdep.h"
3db64b00 23#include "bfd.h"
d70c5fc7
NC
24#include "libbfd.h"
25#include "elf-bfd.h"
26#include "elf/xc16x.h"
fa8f86ff 27#include "dwarf2.h"
d70c5fc7
NC
28#include "libiberty.h"
29
30static reloc_howto_type xc16x_elf_howto_table [] =
31{
32 /* This reloc does nothing. */
33 HOWTO (R_XC16X_NONE, /* type */
34 0, /* rightshift */
6346d5ca
AM
35 3, /* size (0 = byte, 1 = short, 2 = long) */
36 0, /* bitsize */
d70c5fc7
NC
37 FALSE, /* pc_relative */
38 0, /* bitpos */
6346d5ca 39 complain_overflow_dont, /* complain_on_overflow */
d70c5fc7
NC
40 bfd_elf_generic_reloc, /* special_function */
41 "R_XC16X_NONE", /* name */
42 FALSE, /* partial_inplace */
43 0, /* src_mask */
44 0, /* dst_mask */
45 FALSE), /* pcrel_offset */
46
47 /* An 8 bit absolute relocation. */
48 HOWTO (R_XC16X_ABS_8, /* type */
49 0, /* rightshift */
50 0, /* size (0 = byte, 1 = short, 2 = long) */
51 8, /* bitsize */
52 FALSE, /* pc_relative */
53 8, /* bitpos */
54 complain_overflow_bitfield, /* complain_on_overflow */
55 bfd_elf_generic_reloc, /* special_function */
56 "R_XC16X_ABS_8", /* name */
57 TRUE, /* partial_inplace */
58 0x0000, /* src_mask */
59 0x00ff, /* dst_mask */
60 FALSE), /* pcrel_offset */
61
62 /* A 16 bit absolute relocation. */
63 HOWTO (R_XC16X_ABS_16, /* type */
64 0, /* rightshift */
65 1, /* size (0 = byte, 1 = short, 2 = long) */
66 16, /* bitsize */
67 FALSE, /* pc_relative */
68 0, /* bitpos */
69 complain_overflow_dont, /* complain_on_overflow */
70 bfd_elf_generic_reloc, /* special_function */
71 "R_XC16X_ABS_16", /* name */
72 TRUE, /* partial_inplace */
73 0x00000000, /* src_mask */
74 0x0000ffff, /* dst_mask */
75 FALSE), /* pcrel_offset */
76
77 HOWTO (R_XC16X_ABS_32, /* type */
07d6d2b8
AM
78 0, /* rightshift */
79 2, /* size (0 = byte, 1 = short, 2 = long) */
80 32, /* bitsize */
81 FALSE, /* pc_relative */
82 0, /* bitpos */
83 complain_overflow_bitfield, /* complain_on_overflow */
84 bfd_elf_generic_reloc, /* special_function */
85 "R_XC16X_ABS_32", /* name */
86 TRUE, /* partial_inplace */
87 0x00000000, /* src_mask */
88 0xffffffff, /* dst_mask */
89 FALSE), /* pcrel_offset */
d70c5fc7
NC
90
91
92 /* A PC relative 8 bit relocation. */
93 HOWTO (R_XC16X_8_PCREL, /* type */
94 0, /* rightshift */
95 0, /* size (0 = byte, 1 = short, 2 = long) */
96 8, /* bitsize */
97 TRUE, /* pc_relative */
98 8, /* bitpos */
99 complain_overflow_signed, /* complain_on_overflow */
100 bfd_elf_generic_reloc, /* special_function */
101 "R_XC16X_8_PCREL", /* name */
102 FALSE, /* partial_inplace */
103 0x0000, /* src_mask */
104 0x00ff, /* dst_mask */
105 TRUE), /* pcrel_offset */
106
107 /* Relocation regarding page number. */
108 HOWTO (R_XC16X_PAG, /* type */
07d6d2b8
AM
109 0, /* rightshift */
110 1, /* size (0 = byte, 1 = short, 2 = long) */
111 16, /* bitsize */
112 FALSE, /* pc_relative */
113 0, /* bitpos */
114 complain_overflow_signed, /* complain_on_overflow */
115 bfd_elf_generic_reloc, /* special_function */
116 "R_XC16X_PAG", /* name */
117 TRUE, /* partial_inplace */
118 0x00000000, /* src_mask */
119 0x0000ffff, /* dst_mask */
120 FALSE), /* pcrel_offset */
d70c5fc7
NC
121
122
123 /* Relocation regarding page number. */
124 HOWTO (R_XC16X_POF, /* type */
07d6d2b8
AM
125 0, /* rightshift */
126 1, /* size (0 = byte, 1 = short, 2 = long) */
127 16, /* bitsize */
128 FALSE, /* pc_relative */
129 0, /* bitpos */
130 complain_overflow_signed, /* complain_on_overflow */
131 bfd_elf_generic_reloc, /* special_function */
132 "R_XC16X_POF", /* name */
133 TRUE, /* partial_inplace */
134 0x00000000, /* src_mask */
135 0x0000ffff, /* dst_mask */
136 FALSE), /* pcrel_offset */
d70c5fc7
NC
137
138
139 /* Relocation regarding segment number. */
140 HOWTO (R_XC16X_SEG, /* type */
07d6d2b8
AM
141 0, /* rightshift */
142 1, /* size (0 = byte, 1 = short, 2 = long) */
143 16, /* bitsize */
144 FALSE, /* pc_relative */
145 0, /* bitpos */
146 complain_overflow_signed, /* complain_on_overflow */
147 bfd_elf_generic_reloc, /* special_function */
148 "R_XC16X_SEG", /* name */
149 TRUE, /* partial_inplace */
150 0x00000000, /* src_mask */
151 0x0000ffff, /* dst_mask */
152 FALSE), /* pcrel_offset */
d70c5fc7
NC
153
154 /* Relocation regarding segment offset. */
155 HOWTO (R_XC16X_SOF, /* type */
07d6d2b8
AM
156 0, /* rightshift */
157 1, /* size (0 = byte, 1 = short, 2 = long) */
158 16, /* bitsize */
159 FALSE, /* pc_relative */
160 0, /* bitpos */
161 complain_overflow_signed, /* complain_on_overflow */
162 bfd_elf_generic_reloc, /* special_function */
163 "R_XC16X_SOF", /* name */
164 TRUE, /* partial_inplace */
165 0x00000000, /* src_mask */
166 0x0000ffff, /* dst_mask */
167 FALSE) /* pcrel_offset */
d70c5fc7
NC
168};
169
170
171/* Map BFD reloc types to XC16X ELF reloc types. */
172
173struct xc16x_reloc_map
174{
175 bfd_reloc_code_real_type bfd_reloc_val;
176 unsigned int xc16x_reloc_val;
177};
178
179static const struct xc16x_reloc_map xc16x_reloc_map [] =
180{
07d6d2b8
AM
181 { BFD_RELOC_NONE, R_XC16X_NONE },
182 { BFD_RELOC_8, R_XC16X_ABS_8 },
183 { BFD_RELOC_16, R_XC16X_ABS_16 },
184 { BFD_RELOC_32, R_XC16X_ABS_32 },
185 { BFD_RELOC_8_PCREL, R_XC16X_8_PCREL },
d70c5fc7
NC
186 { BFD_RELOC_XC16X_PAG, R_XC16X_PAG},
187 { BFD_RELOC_XC16X_POF, R_XC16X_POF},
188 { BFD_RELOC_XC16X_SEG, R_XC16X_SEG},
189 { BFD_RELOC_XC16X_SOF, R_XC16X_SOF},
190};
191
192
193/* This function is used to search for correct relocation type from
194 howto structure. */
195
196static reloc_howto_type *
197xc16x_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
198 bfd_reloc_code_real_type code)
199{
200 unsigned int i;
201
202 for (i = ARRAY_SIZE (xc16x_reloc_map); --i;)
203 if (xc16x_reloc_map [i].bfd_reloc_val == code)
204 return & xc16x_elf_howto_table [xc16x_reloc_map[i].xc16x_reloc_val];
205
206 return NULL;
207}
208
157090f7
AM
209static reloc_howto_type *
210xc16x_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
211 const char *r_name)
212{
213 unsigned int i;
214
f3185997 215 for (i = 0; i < ARRAY_SIZE (xc16x_elf_howto_table); i++)
157090f7
AM
216 if (xc16x_elf_howto_table[i].name != NULL
217 && strcasecmp (xc16x_elf_howto_table[i].name, r_name) == 0)
218 return &xc16x_elf_howto_table[i];
219
220 return NULL;
221}
222
d70c5fc7
NC
223/* For a particular operand this function is
224 called to finalise the type of relocation. */
225
f3185997
NC
226static bfd_boolean
227elf32_xc16x_info_to_howto (bfd *abfd, arelent *bfd_reloc,
d70c5fc7
NC
228 Elf_Internal_Rela *elf_reloc)
229{
230 unsigned int r;
231 unsigned int i;
232
233 r = ELF32_R_TYPE (elf_reloc->r_info);
234 for (i = 0; i < ARRAY_SIZE (xc16x_elf_howto_table); i++)
235 if (xc16x_elf_howto_table[i].type == r)
236 {
237 bfd_reloc->howto = &xc16x_elf_howto_table[i];
f3185997 238 return TRUE;
d70c5fc7 239 }
f3185997
NC
240 /* xgettext:c-format */
241 _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, r);
242 bfd_set_error (bfd_error_bad_value);
243 return FALSE;
d70c5fc7
NC
244}
245
246static bfd_reloc_status_type
247elf32_xc16x_final_link_relocate (unsigned long r_type,
248 bfd *input_bfd,
249 bfd *output_bfd ATTRIBUTE_UNUSED,
250 asection *input_section ATTRIBUTE_UNUSED,
251 bfd_byte *contents,
252 bfd_vma offset,
253 bfd_vma value,
254 bfd_vma addend,
255 struct bfd_link_info *info ATTRIBUTE_UNUSED,
256 asection *sym_sec ATTRIBUTE_UNUSED,
257 int is_local ATTRIBUTE_UNUSED)
258{
259 bfd_byte *hit_data = contents + offset;
260 bfd_vma val1;
261
262 switch (r_type)
263 {
264 case R_XC16X_NONE:
265 return bfd_reloc_ok;
266
267 case R_XC16X_ABS_16:
268 value += addend;
269 bfd_put_16 (input_bfd, value, hit_data);
270 return bfd_reloc_ok;
271
272 case R_XC16X_8_PCREL:
273 bfd_put_8 (input_bfd, value, hit_data);
274 return bfd_reloc_ok;
275
276 /* Following case is to find page number from actual
277 address for this divide value by 16k i.e. page size. */
278
279 case R_XC16X_PAG:
280 value += addend;
281 value /= 0x4000;
282 bfd_put_16 (input_bfd, value, hit_data);
283 return bfd_reloc_ok;
284
285 /* Following case is to find page offset from actual address
286 for this take modulo of value by 16k i.e. page size. */
287
288 case R_XC16X_POF:
289 value += addend;
290 value %= 0x4000;
291 bfd_put_16 (input_bfd, value, hit_data);
292 return bfd_reloc_ok;
293
294 /* Following case is to find segment number from actual
295 address for this divide value by 64k i.e. segment size. */
296
297 case R_XC16X_SEG:
298 value += addend;
299 value /= 0x10000;
300 bfd_put_16 (input_bfd, value, hit_data);
301 return bfd_reloc_ok;
302
303 /* Following case is to find segment offset from actual address
304 for this take modulo of value by 64k i.e. segment size. */
305
306 case R_XC16X_SOF:
307 value += addend;
308 value %= 0x10000;
309 bfd_put_16 (input_bfd, value, hit_data);
310 return bfd_reloc_ok;
311
312 case R_XC16X_ABS_32:
313 if (!strstr (input_section->name,".debug"))
314 {
315 value += addend;
316 val1 = value;
317 value %= 0x4000;
318 val1 /= 0x4000;
319 val1 = val1 << 16;
320 value += val1;
321 bfd_put_32 (input_bfd, value, hit_data);
322 }
323 else
324 {
325 value += addend;
326 bfd_put_32 (input_bfd, value, hit_data);
327 }
328 return bfd_reloc_ok;
329
330 default:
331 return bfd_reloc_notsupported;
332 }
333}
334
335static bfd_boolean
336elf32_xc16x_relocate_section (bfd *output_bfd,
337 struct bfd_link_info *info,
338 bfd *input_bfd,
339 asection *input_section,
340 bfd_byte *contents,
341 Elf_Internal_Rela *relocs,
342 Elf_Internal_Sym *local_syms,
343 asection **local_sections)
344{
345 Elf_Internal_Shdr *symtab_hdr;
346 struct elf_link_hash_entry **sym_hashes;
347 Elf_Internal_Rela *rel, *relend;
348
d70c5fc7
NC
349 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
350 sym_hashes = elf_sym_hashes (input_bfd);
351
352 rel = relocs;
353 relend = relocs + input_section->reloc_count;
354 for (; rel < relend; rel++)
355 {
356 unsigned int r_type;
357 unsigned long r_symndx;
358 Elf_Internal_Sym *sym;
359 asection *sec;
360 struct elf_link_hash_entry *h;
361 bfd_vma relocation;
d70c5fc7
NC
362
363 /* This is a final link. */
364 r_symndx = ELF32_R_SYM (rel->r_info);
365 r_type = ELF32_R_TYPE (rel->r_info);
366 h = NULL;
367 sym = NULL;
368 sec = NULL;
369 if (r_symndx < symtab_hdr->sh_info)
370 {
371 sym = local_syms + r_symndx;
372 sec = local_sections[r_symndx];
373 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
374 }
375 else
376 {
62d887d4 377 bfd_boolean unresolved_reloc, warned, ignored;
d70c5fc7
NC
378
379 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
380 r_symndx, symtab_hdr, sym_hashes,
381 h, sec, relocation,
62d887d4 382 unresolved_reloc, warned, ignored);
d70c5fc7
NC
383 }
384
dbaa2011 385 if (sec != NULL && discarded_section (sec))
ab96bf03
AM
386 {
387 /* For relocs against symbols from removed linkonce sections,
388 or sections discarded by a linker script, we just want the
e4067dbb 389 section contents cleared. Avoid any special processing. */
ab96bf03
AM
390 reloc_howto_type *howto;
391 howto = xc16x_reloc_type_lookup (input_bfd, r_type);
e4067dbb 392 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
545fd46b 393 rel, 1, relend, howto, 0, contents);
ab96bf03
AM
394 }
395
0e1862bb 396 if (bfd_link_relocatable (info))
ab96bf03
AM
397 continue;
398
c7e2358a
AM
399 elf32_xc16x_final_link_relocate (r_type, input_bfd, output_bfd,
400 input_section,
401 contents, rel->r_offset,
402 relocation, rel->r_addend,
403 info, sec, h == NULL);
d70c5fc7
NC
404 }
405
406 return TRUE;
407}
408
409
410static void
411elf32_xc16x_final_write_processing (bfd *abfd,
412 bfd_boolean linker ATTRIBUTE_UNUSED)
413{
414 unsigned long val;
415
416 switch (bfd_get_mach (abfd))
417 {
418 default:
419 case bfd_mach_xc16x:
420 val = 0x1000;
421 break;
422
423 case bfd_mach_xc16xl:
424 val = 0x1001;
425 break;
426
427 case bfd_mach_xc16xs:
428 val = 0x1002;
429 break;
430 }
431
432 elf_elfheader (abfd)->e_flags |= val;
433}
434
435static unsigned long
436elf32_xc16x_mach (flagword flags)
68ffbac6 437{
d70c5fc7
NC
438 switch (flags)
439 {
440 case 0x1000:
68ffbac6 441 default:
d70c5fc7
NC
442 return bfd_mach_xc16x;
443
444 case 0x1001:
445 return bfd_mach_xc16xl;
446
447 case 0x1002:
448 return bfd_mach_xc16xs;
449 }
450}
451
452
453static bfd_boolean
454elf32_xc16x_object_p (bfd *abfd)
455{
456 bfd_default_set_arch_mach (abfd, bfd_arch_xc16x,
457 elf32_xc16x_mach (elf_elfheader (abfd)->e_flags));
458 return TRUE;
459}
460
461
462#define ELF_ARCH bfd_arch_xc16x
463#define ELF_MACHINE_CODE EM_XC16X
464#define ELF_MAXPAGESIZE 0x100
465
6d00b590 466#define TARGET_LITTLE_SYM xc16x_elf32_vec
d70c5fc7
NC
467#define TARGET_LITTLE_NAME "elf32-xc16x"
468#define elf_backend_final_write_processing elf32_xc16x_final_write_processing
07d6d2b8 469#define elf_backend_object_p elf32_xc16x_object_p
d70c5fc7
NC
470#define elf_backend_can_gc_sections 1
471#define bfd_elf32_bfd_reloc_type_lookup xc16x_reloc_type_lookup
157090f7 472#define bfd_elf32_bfd_reloc_name_lookup xc16x_reloc_name_lookup
d70c5fc7
NC
473#define elf_info_to_howto elf32_xc16x_info_to_howto
474#define elf_info_to_howto_rel elf32_xc16x_info_to_howto
07d6d2b8 475#define elf_backend_relocate_section elf32_xc16x_relocate_section
d70c5fc7
NC
476#define elf_backend_rela_normal 1
477
478#include "elf32-target.h"
This page took 0.647637 seconds and 4 git commands to generate.