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.
b90efa5b 2 Copyright (C) 2006-2015 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 */
35 1, /* size (0 = byte, 1 = short, 2 = long) */
36 16, /* bitsize */
37 FALSE, /* pc_relative */
38 0, /* bitpos */
39 complain_overflow_bitfield, /* complain_on_overflow */
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 */
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 */
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 */
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 */
121
122
123 /* Relocation regarding page number. */
124 HOWTO (R_XC16X_POF, /* type */
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 */
137
138
139 /* Relocation regarding segment number. */
140 HOWTO (R_XC16X_SEG, /* type */
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 */
153
154 /* Relocation regarding segment offset. */
155 HOWTO (R_XC16X_SOF, /* type */
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 */
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{
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 },
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
215 for (i = 0;
216 i < sizeof (xc16x_elf_howto_table) / sizeof (xc16x_elf_howto_table[0]);
217 i++)
218 if (xc16x_elf_howto_table[i].name != NULL
219 && strcasecmp (xc16x_elf_howto_table[i].name, r_name) == 0)
220 return &xc16x_elf_howto_table[i];
221
222 return NULL;
223}
224
d70c5fc7
NC
225/* For a particular operand this function is
226 called to finalise the type of relocation. */
227
228static void
229elf32_xc16x_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *bfd_reloc,
230 Elf_Internal_Rela *elf_reloc)
231{
232 unsigned int r;
233 unsigned int i;
234
235 r = ELF32_R_TYPE (elf_reloc->r_info);
236 for (i = 0; i < ARRAY_SIZE (xc16x_elf_howto_table); i++)
237 if (xc16x_elf_howto_table[i].type == r)
238 {
239 bfd_reloc->howto = &xc16x_elf_howto_table[i];
240 return;
241 }
242 abort ();
243}
244
245static bfd_reloc_status_type
246elf32_xc16x_final_link_relocate (unsigned long r_type,
247 bfd *input_bfd,
248 bfd *output_bfd ATTRIBUTE_UNUSED,
249 asection *input_section ATTRIBUTE_UNUSED,
250 bfd_byte *contents,
251 bfd_vma offset,
252 bfd_vma value,
253 bfd_vma addend,
254 struct bfd_link_info *info ATTRIBUTE_UNUSED,
255 asection *sym_sec ATTRIBUTE_UNUSED,
256 int is_local ATTRIBUTE_UNUSED)
257{
258 bfd_byte *hit_data = contents + offset;
259 bfd_vma val1;
260
261 switch (r_type)
262 {
263 case R_XC16X_NONE:
264 return bfd_reloc_ok;
265
266 case R_XC16X_ABS_16:
267 value += addend;
268 bfd_put_16 (input_bfd, value, hit_data);
269 return bfd_reloc_ok;
270
271 case R_XC16X_8_PCREL:
272 bfd_put_8 (input_bfd, value, hit_data);
273 return bfd_reloc_ok;
274
275 /* Following case is to find page number from actual
276 address for this divide value by 16k i.e. page size. */
277
278 case R_XC16X_PAG:
279 value += addend;
280 value /= 0x4000;
281 bfd_put_16 (input_bfd, value, hit_data);
282 return bfd_reloc_ok;
283
284 /* Following case is to find page offset from actual address
285 for this take modulo of value by 16k i.e. page size. */
286
287 case R_XC16X_POF:
288 value += addend;
289 value %= 0x4000;
290 bfd_put_16 (input_bfd, value, hit_data);
291 return bfd_reloc_ok;
292
293 /* Following case is to find segment number from actual
294 address for this divide value by 64k i.e. segment size. */
295
296 case R_XC16X_SEG:
297 value += addend;
298 value /= 0x10000;
299 bfd_put_16 (input_bfd, value, hit_data);
300 return bfd_reloc_ok;
301
302 /* Following case is to find segment offset from actual address
303 for this take modulo of value by 64k i.e. segment size. */
304
305 case R_XC16X_SOF:
306 value += addend;
307 value %= 0x10000;
308 bfd_put_16 (input_bfd, value, hit_data);
309 return bfd_reloc_ok;
310
311 case R_XC16X_ABS_32:
312 if (!strstr (input_section->name,".debug"))
313 {
314 value += addend;
315 val1 = value;
316 value %= 0x4000;
317 val1 /= 0x4000;
318 val1 = val1 << 16;
319 value += val1;
320 bfd_put_32 (input_bfd, value, hit_data);
321 }
322 else
323 {
324 value += addend;
325 bfd_put_32 (input_bfd, value, hit_data);
326 }
327 return bfd_reloc_ok;
328
329 default:
330 return bfd_reloc_notsupported;
331 }
332}
333
334static bfd_boolean
335elf32_xc16x_relocate_section (bfd *output_bfd,
336 struct bfd_link_info *info,
337 bfd *input_bfd,
338 asection *input_section,
339 bfd_byte *contents,
340 Elf_Internal_Rela *relocs,
341 Elf_Internal_Sym *local_syms,
342 asection **local_sections)
343{
344 Elf_Internal_Shdr *symtab_hdr;
345 struct elf_link_hash_entry **sym_hashes;
346 Elf_Internal_Rela *rel, *relend;
347
d70c5fc7
NC
348 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
349 sym_hashes = elf_sym_hashes (input_bfd);
350
351 rel = relocs;
352 relend = relocs + input_section->reloc_count;
353 for (; rel < relend; rel++)
354 {
355 unsigned int r_type;
356 unsigned long r_symndx;
357 Elf_Internal_Sym *sym;
358 asection *sec;
359 struct elf_link_hash_entry *h;
360 bfd_vma relocation;
d70c5fc7
NC
361
362 /* This is a final link. */
363 r_symndx = ELF32_R_SYM (rel->r_info);
364 r_type = ELF32_R_TYPE (rel->r_info);
365 h = NULL;
366 sym = NULL;
367 sec = NULL;
368 if (r_symndx < symtab_hdr->sh_info)
369 {
370 sym = local_syms + r_symndx;
371 sec = local_sections[r_symndx];
372 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
373 }
374 else
375 {
62d887d4 376 bfd_boolean unresolved_reloc, warned, ignored;
d70c5fc7
NC
377
378 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
379 r_symndx, symtab_hdr, sym_hashes,
380 h, sec, relocation,
62d887d4 381 unresolved_reloc, warned, ignored);
d70c5fc7
NC
382 }
383
dbaa2011 384 if (sec != NULL && discarded_section (sec))
ab96bf03
AM
385 {
386 /* For relocs against symbols from removed linkonce sections,
387 or sections discarded by a linker script, we just want the
e4067dbb 388 section contents cleared. Avoid any special processing. */
ab96bf03
AM
389 reloc_howto_type *howto;
390 howto = xc16x_reloc_type_lookup (input_bfd, r_type);
e4067dbb 391 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
545fd46b 392 rel, 1, relend, howto, 0, contents);
ab96bf03
AM
393 }
394
395 if (info->relocatable)
396 continue;
397
c7e2358a
AM
398 elf32_xc16x_final_link_relocate (r_type, input_bfd, output_bfd,
399 input_section,
400 contents, rel->r_offset,
401 relocation, rel->r_addend,
402 info, sec, h == NULL);
d70c5fc7
NC
403 }
404
405 return TRUE;
406}
407
408
409static void
410elf32_xc16x_final_write_processing (bfd *abfd,
411 bfd_boolean linker ATTRIBUTE_UNUSED)
412{
413 unsigned long val;
414
415 switch (bfd_get_mach (abfd))
416 {
417 default:
418 case bfd_mach_xc16x:
419 val = 0x1000;
420 break;
421
422 case bfd_mach_xc16xl:
423 val = 0x1001;
424 break;
425
426 case bfd_mach_xc16xs:
427 val = 0x1002;
428 break;
429 }
430
431 elf_elfheader (abfd)->e_flags |= val;
432}
433
434static unsigned long
435elf32_xc16x_mach (flagword flags)
68ffbac6 436{
d70c5fc7
NC
437 switch (flags)
438 {
439 case 0x1000:
68ffbac6 440 default:
d70c5fc7
NC
441 return bfd_mach_xc16x;
442
443 case 0x1001:
444 return bfd_mach_xc16xl;
445
446 case 0x1002:
447 return bfd_mach_xc16xs;
448 }
449}
450
451
452static bfd_boolean
453elf32_xc16x_object_p (bfd *abfd)
454{
455 bfd_default_set_arch_mach (abfd, bfd_arch_xc16x,
456 elf32_xc16x_mach (elf_elfheader (abfd)->e_flags));
457 return TRUE;
458}
459
460
461#define ELF_ARCH bfd_arch_xc16x
462#define ELF_MACHINE_CODE EM_XC16X
463#define ELF_MAXPAGESIZE 0x100
464
6d00b590 465#define TARGET_LITTLE_SYM xc16x_elf32_vec
d70c5fc7
NC
466#define TARGET_LITTLE_NAME "elf32-xc16x"
467#define elf_backend_final_write_processing elf32_xc16x_final_write_processing
468#define elf_backend_object_p elf32_xc16x_object_p
469#define elf_backend_can_gc_sections 1
470#define bfd_elf32_bfd_reloc_type_lookup xc16x_reloc_type_lookup
157090f7 471#define bfd_elf32_bfd_reloc_name_lookup xc16x_reloc_name_lookup
d70c5fc7
NC
472#define elf_info_to_howto elf32_xc16x_info_to_howto
473#define elf_info_to_howto_rel elf32_xc16x_info_to_howto
474#define elf_backend_relocate_section elf32_xc16x_relocate_section
475#define elf_backend_rela_normal 1
476
477#include "elf32-target.h"
This page took 0.461984 seconds and 4 git commands to generate.