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