2004-04-21 Andrew Cagney <cagney@redhat.com>
[binutils.git] / bfd / elf32-msp430.c
blobdfe33bd246fbf4fbad78a1c2bc21fb3a6cf51284
1 /* MSP430-specific support for 32-bit ELF
2 Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
3 Contributed by Dmitry Diky <diwil@mail.ru>
5 This file is part of BFD, the Binary File Descriptor library.
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
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
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.
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
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libiberty.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/msp430.h"
28 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
29 PARAMS ((bfd *, bfd_reloc_code_real_type));
31 static void msp430_info_to_howto_rela
32 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
34 static asection *elf32_msp430_gc_mark_hook
35 PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
36 struct elf_link_hash_entry *, Elf_Internal_Sym *));
38 static bfd_boolean elf32_msp430_gc_sweep_hook
39 PARAMS ((bfd *, struct bfd_link_info *, asection *,
40 const Elf_Internal_Rela *));
42 static bfd_boolean elf32_msp430_check_relocs
43 PARAMS ((bfd *, struct bfd_link_info *, asection *,
44 const Elf_Internal_Rela *));
46 static bfd_reloc_status_type msp430_final_link_relocate
47 PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
48 Elf_Internal_Rela *, bfd_vma));
50 static bfd_boolean elf32_msp430_relocate_section
51 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
52 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
54 static void bfd_elf_msp430_final_write_processing
55 PARAMS ((bfd *, bfd_boolean));
57 static bfd_boolean elf32_msp430_object_p
58 PARAMS ((bfd *));
60 static void elf32_msp430_post_process_headers
61 PARAMS ((bfd *, struct bfd_link_info *));
63 /* Use RELA instead of REL. */
64 #undef USE_REL
66 static reloc_howto_type elf_msp430_howto_table[] =
68 HOWTO (R_MSP430_NONE, /* type */
69 0, /* rightshift */
70 2, /* size (0 = byte, 1 = short, 2 = long) */
71 32, /* bitsize */
72 FALSE, /* pc_relative */
73 0, /* bitpos */
74 complain_overflow_bitfield, /* complain_on_overflow */
75 bfd_elf_generic_reloc, /* special_function */
76 "R_MSP430_NONE", /* name */
77 FALSE, /* partial_inplace */
78 0, /* src_mask */
79 0, /* dst_mask */
80 FALSE), /* pcrel_offset */
82 HOWTO (R_MSP430_32, /* type */
83 0, /* rightshift */
84 2, /* size (0 = byte, 1 = short, 2 = long) */
85 32, /* bitsize */
86 FALSE, /* pc_relative */
87 0, /* bitpos */
88 complain_overflow_bitfield, /* complain_on_overflow */
89 bfd_elf_generic_reloc, /* special_function */
90 "R_MSP430_32", /* name */
91 FALSE, /* partial_inplace */
92 0xffffffff, /* src_mask */
93 0xffffffff, /* dst_mask */
94 FALSE), /* pcrel_offset */
96 /* A 13 bit PC relative relocation. */
97 HOWTO (R_MSP430_10_PCREL, /* type */
98 1, /* rightshift */
99 1, /* size (0 = byte, 1 = short, 2 = long) */
100 10, /* bitsize */
101 TRUE, /* pc_relative */
102 0, /* bitpos */
103 complain_overflow_bitfield, /* complain_on_overflow */
104 bfd_elf_generic_reloc, /* special_function */
105 "R_MSP430_13_PCREL", /* name */
106 FALSE, /* partial_inplace */
107 0xfff, /* src_mask */
108 0xfff, /* dst_mask */
109 TRUE), /* pcrel_offset */
111 /* A 16 bit absolute relocation. */
112 HOWTO (R_MSP430_16, /* type */
113 0, /* rightshift */
114 1, /* size (0 = byte, 1 = short, 2 = long) */
115 16, /* bitsize */
116 FALSE, /* pc_relative */
117 0, /* bitpos */
118 complain_overflow_dont,/* complain_on_overflow */
119 bfd_elf_generic_reloc, /* special_function */
120 "R_MSP430_16", /* name */
121 FALSE, /* partial_inplace */
122 0xffff, /* src_mask */
123 0xffff, /* dst_mask */
124 FALSE), /* pcrel_offset */
126 /* A 16 bit absolute relocation for command address. */
127 HOWTO (R_MSP430_16_PCREL, /* type */
128 1, /* rightshift */
129 1, /* size (0 = byte, 1 = short, 2 = long) */
130 16, /* bitsize */
131 TRUE, /* pc_relative */
132 0, /* bitpos */
133 complain_overflow_dont,/* complain_on_overflow */
134 bfd_elf_generic_reloc, /* special_function */
135 "R_MSP430_16_PCREL", /* name */
136 FALSE, /* partial_inplace */
137 0xffff, /* src_mask */
138 0xffff, /* dst_mask */
139 TRUE), /* pcrel_offset */
141 /* A 16 bit absolute relocation, byte operations. */
142 HOWTO (R_MSP430_16_BYTE, /* type */
143 0, /* rightshift */
144 1, /* size (0 = byte, 1 = short, 2 = long) */
145 16, /* bitsize */
146 FALSE, /* pc_relative */
147 0, /* bitpos */
148 complain_overflow_dont,/* complain_on_overflow */
149 bfd_elf_generic_reloc, /* special_function */
150 "R_MSP430_16_BYTE", /* name */
151 FALSE, /* partial_inplace */
152 0xffff, /* src_mask */
153 0xffff, /* dst_mask */
154 FALSE), /* pcrel_offset */
156 /* A 16 bit absolute relocation for command address. */
157 HOWTO (R_MSP430_16_PCREL_BYTE,/* type */
158 1, /* rightshift */
159 1, /* size (0 = byte, 1 = short, 2 = long) */
160 16, /* bitsize */
161 TRUE, /* pc_relative */
162 0, /* bitpos */
163 complain_overflow_dont,/* complain_on_overflow */
164 bfd_elf_generic_reloc, /* special_function */
165 "R_MSP430_16_PCREL_BYTE", /* name */
166 FALSE, /* partial_inplace */
167 0xffff, /* src_mask */
168 0xffff, /* dst_mask */
169 TRUE) /* pcrel_offset */
172 /* Map BFD reloc types to MSP430 ELF reloc types. */
174 struct msp430_reloc_map
176 bfd_reloc_code_real_type bfd_reloc_val;
177 unsigned int elf_reloc_val;
180 static const struct msp430_reloc_map msp430_reloc_map[] =
182 {BFD_RELOC_NONE, R_MSP430_NONE},
183 {BFD_RELOC_32, R_MSP430_32},
184 {BFD_RELOC_MSP430_10_PCREL, R_MSP430_10_PCREL},
185 {BFD_RELOC_16, R_MSP430_16_BYTE},
186 {BFD_RELOC_MSP430_16_PCREL, R_MSP430_16_PCREL},
187 {BFD_RELOC_MSP430_16, R_MSP430_16},
188 {BFD_RELOC_MSP430_16_PCREL_BYTE, R_MSP430_16_PCREL_BYTE},
189 {BFD_RELOC_MSP430_16_BYTE, R_MSP430_16_BYTE}
192 static reloc_howto_type *
193 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
194 bfd *abfd ATTRIBUTE_UNUSED;
195 bfd_reloc_code_real_type code;
197 unsigned int i;
199 for (i = 0; i < ARRAY_SIZE (msp430_reloc_map); i++)
200 if (msp430_reloc_map[i].bfd_reloc_val == code)
201 return &elf_msp430_howto_table[msp430_reloc_map[i].elf_reloc_val];
203 return NULL;
206 /* Set the howto pointer for an MSP430 ELF reloc. */
208 static void
209 msp430_info_to_howto_rela (abfd, cache_ptr, dst)
210 bfd *abfd ATTRIBUTE_UNUSED;
211 arelent *cache_ptr;
212 Elf_Internal_Rela *dst;
214 unsigned int r_type;
216 r_type = ELF32_R_TYPE (dst->r_info);
217 BFD_ASSERT (r_type < (unsigned int) R_MSP430_max);
218 cache_ptr->howto = &elf_msp430_howto_table[r_type];
221 static asection *
222 elf32_msp430_gc_mark_hook (sec, info, rel, h, sym)
223 asection *sec;
224 struct bfd_link_info *info ATTRIBUTE_UNUSED;
225 Elf_Internal_Rela *rel;
226 struct elf_link_hash_entry *h;
227 Elf_Internal_Sym *sym;
229 if (h != NULL)
231 switch (ELF32_R_TYPE (rel->r_info))
233 default:
234 switch (h->root.type)
236 case bfd_link_hash_defined:
237 case bfd_link_hash_defweak:
238 return h->root.u.def.section;
240 case bfd_link_hash_common:
241 return h->root.u.c.p->section;
243 default:
244 break;
248 else
249 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
251 return NULL;
254 static bfd_boolean
255 elf32_msp430_gc_sweep_hook (abfd, info, sec, relocs)
256 bfd *abfd ATTRIBUTE_UNUSED;
257 struct bfd_link_info *info ATTRIBUTE_UNUSED;
258 asection *sec ATTRIBUTE_UNUSED;
259 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
261 /* We don't use got and plt entries for msp430. */
262 return TRUE;
265 /* Look through the relocs for a section during the first phase.
266 Since we don't do .gots or .plts, we just need to consider the
267 virtual table relocs for gc. */
269 static bfd_boolean
270 elf32_msp430_check_relocs (abfd, info, sec, relocs)
271 bfd *abfd;
272 struct bfd_link_info *info;
273 asection *sec;
274 const Elf_Internal_Rela *relocs;
276 Elf_Internal_Shdr *symtab_hdr;
277 struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
278 const Elf_Internal_Rela *rel;
279 const Elf_Internal_Rela *rel_end;
281 if (info->relocatable)
282 return TRUE;
284 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
285 sym_hashes = elf_sym_hashes (abfd);
286 sym_hashes_end =
287 sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
288 if (!elf_bad_symtab (abfd))
289 sym_hashes_end -= symtab_hdr->sh_info;
291 rel_end = relocs + sec->reloc_count;
292 for (rel = relocs; rel < rel_end; rel++)
294 struct elf_link_hash_entry *h;
295 unsigned long r_symndx;
297 r_symndx = ELF32_R_SYM (rel->r_info);
298 if (r_symndx < symtab_hdr->sh_info)
299 h = NULL;
300 else
301 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
304 return TRUE;
307 /* Perform a single relocation. By default we use the standard BFD
308 routines, but a few relocs, we have to do them ourselves. */
310 static bfd_reloc_status_type
311 msp430_final_link_relocate (howto, input_bfd, input_section,
312 contents, rel, relocation)
313 reloc_howto_type *howto;
314 bfd *input_bfd;
315 asection *input_section;
316 bfd_byte *contents;
317 Elf_Internal_Rela *rel;
318 bfd_vma relocation;
320 bfd_reloc_status_type r = bfd_reloc_ok;
321 bfd_vma x;
322 bfd_signed_vma srel;
324 switch (howto->type)
326 case R_MSP430_10_PCREL:
327 contents += rel->r_offset;
328 srel = (bfd_signed_vma) relocation;
329 srel += rel->r_addend;
330 srel -= rel->r_offset;
331 srel -= 2; /* Branch instructions add 2 to the PC... */
332 srel -= (input_section->output_section->vma +
333 input_section->output_offset);
335 if (srel & 1)
336 return bfd_reloc_outofrange;
338 /* MSP430 addresses commands as words. */
339 srel >>= 1;
341 /* Check for an overflow. */
342 if (srel < -512 || srel > 511)
343 return bfd_reloc_overflow;
345 x = bfd_get_16 (input_bfd, contents);
346 x = (x & 0xfc00) | (srel & 0x3ff);
347 bfd_put_16 (input_bfd, x, contents);
348 break;
350 case R_MSP430_16_PCREL:
351 contents += rel->r_offset;
352 srel = (bfd_signed_vma) relocation;
353 srel += rel->r_addend;
354 srel -= rel->r_offset;
355 /* Only branch instructions add 2 to the PC... */
356 srel -= (input_section->output_section->vma +
357 input_section->output_offset);
359 if (srel & 1)
360 return bfd_reloc_outofrange;
362 bfd_put_16 (input_bfd, srel & 0xffff, contents);
363 break;
365 case R_MSP430_16_PCREL_BYTE:
366 contents += rel->r_offset;
367 srel = (bfd_signed_vma) relocation;
368 srel += rel->r_addend;
369 srel -= rel->r_offset;
370 /* Only branch instructions add 2 to the PC... */
371 srel -= (input_section->output_section->vma +
372 input_section->output_offset);
374 bfd_put_16 (input_bfd, srel & 0xffff, contents);
375 break;
377 case R_MSP430_16_BYTE:
378 contents += rel->r_offset;
379 srel = (bfd_signed_vma) relocation;
380 srel += rel->r_addend;
381 bfd_put_16 (input_bfd, srel & 0xffff, contents);
382 break;
384 case R_MSP430_16:
385 contents += rel->r_offset;
386 srel = (bfd_signed_vma) relocation;
387 srel += rel->r_addend;
389 if (srel & 1)
390 return bfd_reloc_notsupported;
392 bfd_put_16 (input_bfd, srel & 0xffff, contents);
393 break;
395 default:
396 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
397 contents, rel->r_offset,
398 relocation, rel->r_addend);
401 return r;
404 /* Relocate an MSP430 ELF section. */
406 static bfd_boolean
407 elf32_msp430_relocate_section (output_bfd, info, input_bfd, input_section,
408 contents, relocs, local_syms, local_sections)
409 bfd *output_bfd ATTRIBUTE_UNUSED;
410 struct bfd_link_info *info;
411 bfd *input_bfd;
412 asection *input_section;
413 bfd_byte *contents;
414 Elf_Internal_Rela *relocs;
415 Elf_Internal_Sym *local_syms;
416 asection **local_sections;
418 Elf_Internal_Shdr *symtab_hdr;
419 struct elf_link_hash_entry **sym_hashes;
420 Elf_Internal_Rela *rel;
421 Elf_Internal_Rela *relend;
423 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
424 sym_hashes = elf_sym_hashes (input_bfd);
425 relend = relocs + input_section->reloc_count;
427 for (rel = relocs; rel < relend; rel++)
429 reloc_howto_type *howto;
430 unsigned long r_symndx;
431 Elf_Internal_Sym *sym;
432 asection *sec;
433 struct elf_link_hash_entry *h;
434 bfd_vma relocation;
435 bfd_reloc_status_type r;
436 const char *name = NULL;
437 int r_type;
439 /* This is a final link. */
441 r_type = ELF32_R_TYPE (rel->r_info);
442 r_symndx = ELF32_R_SYM (rel->r_info);
443 howto = elf_msp430_howto_table + ELF32_R_TYPE (rel->r_info);
444 h = NULL;
445 sym = NULL;
446 sec = NULL;
448 if (r_symndx < symtab_hdr->sh_info)
450 sym = local_syms + r_symndx;
451 sec = local_sections[r_symndx];
452 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
454 name = bfd_elf_string_from_elf_section
455 (input_bfd, symtab_hdr->sh_link, sym->st_name);
456 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
458 else
460 bfd_boolean unresolved_reloc, warned;
462 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
463 r_symndx, symtab_hdr, sym_hashes,
464 h, sec, relocation,
465 unresolved_reloc, warned);
468 r = msp430_final_link_relocate (howto, input_bfd, input_section,
469 contents, rel, relocation);
471 if (r != bfd_reloc_ok)
473 const char *msg = (const char *) NULL;
475 switch (r)
477 case bfd_reloc_overflow:
478 r = info->callbacks->reloc_overflow
479 (info, name, howto->name, (bfd_vma) 0,
480 input_bfd, input_section, rel->r_offset);
481 break;
483 case bfd_reloc_undefined:
484 r = info->callbacks->undefined_symbol
485 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
486 break;
488 case bfd_reloc_outofrange:
489 msg = _("internal error: out of range error");
490 break;
492 case bfd_reloc_notsupported:
493 msg = _("internal error: unsupported relocation error");
494 break;
496 case bfd_reloc_dangerous:
497 msg = _("internal error: dangerous relocation");
498 break;
500 default:
501 msg = _("internal error: unknown error");
502 break;
505 if (msg)
506 r = info->callbacks->warning
507 (info, msg, name, input_bfd, input_section, rel->r_offset);
509 if (!r)
510 return FALSE;
515 return TRUE;
518 /* The final processing done just before writing out a MSP430 ELF object
519 file. This gets the MSP430 architecture right based on the machine
520 number. */
522 static void
523 bfd_elf_msp430_final_write_processing (abfd, linker)
524 bfd *abfd;
525 bfd_boolean linker ATTRIBUTE_UNUSED;
527 unsigned long val;
529 switch (bfd_get_mach (abfd))
531 default:
532 case bfd_mach_msp110:
533 val = E_MSP430_MACH_MSP430x11x1;
534 break;
536 case bfd_mach_msp11:
537 val = E_MSP430_MACH_MSP430x11;
538 break;
540 case bfd_mach_msp12:
541 val = E_MSP430_MACH_MSP430x12;
542 break;
544 case bfd_mach_msp13:
545 val = E_MSP430_MACH_MSP430x13;
546 break;
548 case bfd_mach_msp14:
549 val = E_MSP430_MACH_MSP430x14;
550 break;
552 case bfd_mach_msp15:
553 val = E_MSP430_MACH_MSP430x15;
554 break;
556 case bfd_mach_msp16:
557 val = E_MSP430_MACH_MSP430x16;
558 break;
560 case bfd_mach_msp31:
561 val = E_MSP430_MACH_MSP430x31;
562 break;
564 case bfd_mach_msp32:
565 val = E_MSP430_MACH_MSP430x32;
566 break;
568 case bfd_mach_msp33:
569 val = E_MSP430_MACH_MSP430x33;
570 break;
572 case bfd_mach_msp41:
573 val = E_MSP430_MACH_MSP430x41;
574 break;
576 case bfd_mach_msp42:
577 val = E_MSP430_MACH_MSP430x42;
578 break;
580 case bfd_mach_msp43:
581 val = E_MSP430_MACH_MSP430x43;
582 break;
584 case bfd_mach_msp44:
585 val = E_MSP430_MACH_MSP430x44;
586 break;
589 elf_elfheader (abfd)->e_machine = EM_MSP430;
590 elf_elfheader (abfd)->e_flags &= ~EF_MSP430_MACH;
591 elf_elfheader (abfd)->e_flags |= val;
594 /* Set the right machine number. */
596 static bfd_boolean
597 elf32_msp430_object_p (abfd)
598 bfd *abfd;
600 int e_set = bfd_mach_msp14;
602 if (elf_elfheader (abfd)->e_machine == EM_MSP430
603 || elf_elfheader (abfd)->e_machine == EM_MSP430_OLD)
605 int e_mach = elf_elfheader (abfd)->e_flags & EF_MSP430_MACH;
607 switch (e_mach)
609 default:
610 case E_MSP430_MACH_MSP430x11:
611 e_set = bfd_mach_msp11;
612 break;
614 case E_MSP430_MACH_MSP430x11x1:
615 e_set = bfd_mach_msp110;
616 break;
618 case E_MSP430_MACH_MSP430x12:
619 e_set = bfd_mach_msp12;
620 break;
622 case E_MSP430_MACH_MSP430x13:
623 e_set = bfd_mach_msp13;
624 break;
626 case E_MSP430_MACH_MSP430x14:
627 e_set = bfd_mach_msp14;
628 break;
630 case E_MSP430_MACH_MSP430x15:
631 e_set = bfd_mach_msp15;
632 break;
634 case E_MSP430_MACH_MSP430x16:
635 e_set = bfd_mach_msp16;
636 break;
638 case E_MSP430_MACH_MSP430x31:
639 e_set = bfd_mach_msp31;
640 break;
642 case E_MSP430_MACH_MSP430x32:
643 e_set = bfd_mach_msp32;
644 break;
646 case E_MSP430_MACH_MSP430x33:
647 e_set = bfd_mach_msp33;
648 break;
650 case E_MSP430_MACH_MSP430x41:
651 e_set = bfd_mach_msp41;
652 break;
654 case E_MSP430_MACH_MSP430x42:
655 e_set = bfd_mach_msp42;
656 break;
658 case E_MSP430_MACH_MSP430x43:
659 e_set = bfd_mach_msp43;
660 break;
662 case E_MSP430_MACH_MSP430x44:
663 e_set = bfd_mach_msp44;
664 break;
668 return bfd_default_set_arch_mach (abfd, bfd_arch_msp430, e_set);
671 static void
672 elf32_msp430_post_process_headers (abfd, link_info)
673 bfd *abfd;
674 struct bfd_link_info *link_info ATTRIBUTE_UNUSED;
676 Elf_Internal_Ehdr *i_ehdrp; /* ELF file header, internal form. */
678 i_ehdrp = elf_elfheader (abfd);
680 #ifndef ELFOSABI_STANDALONE
681 #define ELFOSABI_STANDALONE 255
682 #endif
684 i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_STANDALONE;
688 #define ELF_ARCH bfd_arch_msp430
689 #define ELF_MACHINE_CODE EM_MSP430
690 #define ELF_MACHINE_ALT1 EM_MSP430_OLD
691 #define ELF_MAXPAGESIZE 1
693 #define TARGET_LITTLE_SYM bfd_elf32_msp430_vec
694 #define TARGET_LITTLE_NAME "elf32-msp430"
696 #define elf_info_to_howto msp430_info_to_howto_rela
697 #define elf_info_to_howto_rel NULL
698 #define elf_backend_relocate_section elf32_msp430_relocate_section
699 #define elf_backend_gc_mark_hook elf32_msp430_gc_mark_hook
700 #define elf_backend_gc_sweep_hook elf32_msp430_gc_sweep_hook
701 #define elf_backend_check_relocs elf32_msp430_check_relocs
702 #define elf_backend_can_gc_sections 1
703 #define elf_backend_final_write_processing bfd_elf_msp430_final_write_processing
704 #define elf_backend_object_p elf32_msp430_object_p
705 #define elf_backend_post_process_headers elf32_msp430_post_process_headers
707 #include "elf32-target.h"