bfd/
[deliverable/binutils-gdb.git] / bfd / elf32-xc16x.c
CommitLineData
d70c5fc7 1/* Infineon XC16X-specific support for 16-bit ELF.
c7e2358a 2 Copyright 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
d70c5fc7
NC
3 Contributed by KPIT Cummins Infosystems
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 {
376 bfd_boolean unresolved_reloc, warned;
377
378 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
379 r_symndx, symtab_hdr, sym_hashes,
380 h, sec, relocation,
381 unresolved_reloc, warned);
382 }
383
ab96bf03
AM
384 if (sec != NULL && elf_discarded_section (sec))
385 {
386 /* For relocs against symbols from removed linkonce sections,
387 or sections discarded by a linker script, we just want the
388 section contents zeroed. Avoid any special processing. */
389 reloc_howto_type *howto;
390 howto = xc16x_reloc_type_lookup (input_bfd, r_type);
391 _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
392 rel->r_info = 0;
393 rel->r_addend = 0;
394 continue;
395 }
396
397 if (info->relocatable)
398 continue;
399
c7e2358a
AM
400 elf32_xc16x_final_link_relocate (r_type, input_bfd, output_bfd,
401 input_section,
402 contents, rel->r_offset,
403 relocation, rel->r_addend,
404 info, sec, h == NULL);
d70c5fc7
NC
405 }
406
407 return TRUE;
408}
409
410
411static void
412elf32_xc16x_final_write_processing (bfd *abfd,
413 bfd_boolean linker ATTRIBUTE_UNUSED)
414{
415 unsigned long val;
416
417 switch (bfd_get_mach (abfd))
418 {
419 default:
420 case bfd_mach_xc16x:
421 val = 0x1000;
422 break;
423
424 case bfd_mach_xc16xl:
425 val = 0x1001;
426 break;
427
428 case bfd_mach_xc16xs:
429 val = 0x1002;
430 break;
431 }
432
433 elf_elfheader (abfd)->e_flags |= val;
434}
435
436static unsigned long
437elf32_xc16x_mach (flagword flags)
438{
439 switch (flags)
440 {
441 case 0x1000:
442 default:
443 return bfd_mach_xc16x;
444
445 case 0x1001:
446 return bfd_mach_xc16xl;
447
448 case 0x1002:
449 return bfd_mach_xc16xs;
450 }
451}
452
453
454static bfd_boolean
455elf32_xc16x_object_p (bfd *abfd)
456{
457 bfd_default_set_arch_mach (abfd, bfd_arch_xc16x,
458 elf32_xc16x_mach (elf_elfheader (abfd)->e_flags));
459 return TRUE;
460}
461
462
463#define ELF_ARCH bfd_arch_xc16x
464#define ELF_MACHINE_CODE EM_XC16X
465#define ELF_MAXPAGESIZE 0x100
466
467#define TARGET_LITTLE_SYM bfd_elf32_xc16x_vec
468#define TARGET_LITTLE_NAME "elf32-xc16x"
469#define elf_backend_final_write_processing elf32_xc16x_final_write_processing
470#define elf_backend_object_p elf32_xc16x_object_p
471#define elf_backend_can_gc_sections 1
472#define bfd_elf32_bfd_reloc_type_lookup xc16x_reloc_type_lookup
157090f7 473#define bfd_elf32_bfd_reloc_name_lookup xc16x_reloc_name_lookup
d70c5fc7
NC
474#define elf_info_to_howto elf32_xc16x_info_to_howto
475#define elf_info_to_howto_rel elf32_xc16x_info_to_howto
476#define elf_backend_relocate_section elf32_xc16x_relocate_section
477#define elf_backend_rela_normal 1
478
479#include "elf32-target.h"
This page took 0.280147 seconds and 4 git commands to generate.