1 /* MSP430-specific support for 32-bit ELF
2 Copyright (C) 2002, 2003 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. */
23 #include "libiberty.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
60 static void elf32_msp430_post_process_headers
61 PARAMS ((bfd *, struct bfd_link_info *));
63 /* Use RELA instead of REL. */
66 static reloc_howto_type elf_msp430_howto_table[] =
68 HOWTO (R_MSP430_NONE, /* type */
70 2, /* size (0 = byte, 1 = short, 2 = long) */
72 FALSE, /* pc_relative */
74 complain_overflow_bitfield, /* complain_on_overflow */
75 bfd_elf_generic_reloc, /* special_function */
76 "R_MSP430_NONE", /* name */
77 FALSE, /* partial_inplace */
80 FALSE), /* pcrel_offset */
82 HOWTO (R_MSP430_32, /* type */
84 2, /* size (0 = byte, 1 = short, 2 = long) */
86 FALSE, /* pc_relative */
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 */
99 1, /* size (0 = byte, 1 = short, 2 = long) */
101 TRUE, /* pc_relative */
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 */
114 1, /* size (0 = byte, 1 = short, 2 = long) */
116 FALSE, /* pc_relative */
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 */
129 1, /* size (0 = byte, 1 = short, 2 = long) */
131 TRUE, /* pc_relative */
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 */
144 1, /* size (0 = byte, 1 = short, 2 = long) */
146 FALSE, /* pc_relative */
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 */
159 1, /* size (0 = byte, 1 = short, 2 = long) */
161 TRUE, /* pc_relative */
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;
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];
206 /* Set the howto pointer for an MSP430 ELF reloc. */
209 msp430_info_to_howto_rela (abfd, cache_ptr, dst)
210 bfd *abfd ATTRIBUTE_UNUSED;
212 Elf_Internal_Rela *dst;
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];
222 elf32_msp430_gc_mark_hook (sec, info, rel, h, sym)
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;
231 switch (ELF32_R_TYPE (rel->r_info))
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;
249 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
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. */
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. */
270 elf32_msp430_check_relocs (abfd, info, sec, relocs)
272 struct bfd_link_info *info;
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)
284 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
285 sym_hashes = elf_sym_hashes (abfd);
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)
301 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
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;
315 asection *input_section;
317 Elf_Internal_Rela *rel;
320 bfd_reloc_status_type r = bfd_reloc_ok;
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);
336 return bfd_reloc_outofrange;
338 /* MSP430 addresses commands as words. */
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);
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);
360 return bfd_reloc_outofrange;
362 bfd_put_16 (input_bfd, srel & 0xffff, contents);
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);
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);
385 contents += rel->r_offset;
386 srel = (bfd_signed_vma) relocation;
387 srel += rel->r_addend;
390 return bfd_reloc_notsupported;
392 bfd_put_16 (input_bfd, srel & 0xffff, contents);
396 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
397 contents, rel->r_offset,
398 relocation, rel->r_addend);
404 /* Relocate an MSP430 ELF section. */
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;
412 asection *input_section;
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;
433 struct elf_link_hash_entry *h;
435 bfd_reloc_status_type r;
436 const char *name = NULL;
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);
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;
460 bfd_boolean unresolved_reloc, warned;
462 RELOC_FOR_GLOBAL_SYMBOL (h, sym_hashes, r_symndx, symtab_hdr,
463 relocation, sec, unresolved_reloc,
467 r = msp430_final_link_relocate (howto, input_bfd, input_section,
468 contents, rel, relocation);
470 if (r != bfd_reloc_ok)
472 const char *msg = (const char *) NULL;
476 case bfd_reloc_overflow:
477 r = info->callbacks->reloc_overflow
478 (info, name, howto->name, (bfd_vma) 0,
479 input_bfd, input_section, rel->r_offset);
482 case bfd_reloc_undefined:
483 r = info->callbacks->undefined_symbol
484 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
487 case bfd_reloc_outofrange:
488 msg = _("internal error: out of range error");
491 case bfd_reloc_notsupported:
492 msg = _("internal error: unsupported relocation error");
495 case bfd_reloc_dangerous:
496 msg = _("internal error: dangerous relocation");
500 msg = _("internal error: unknown error");
505 r = info->callbacks->warning
506 (info, msg, name, input_bfd, input_section, rel->r_offset);
517 /* The final processing done just before writing out a MSP430 ELF object
518 file. This gets the MSP430 architecture right based on the machine
522 bfd_elf_msp430_final_write_processing (abfd, linker)
524 bfd_boolean linker ATTRIBUTE_UNUSED;
528 switch (bfd_get_mach (abfd))
531 case bfd_mach_msp110:
532 val = E_MSP430_MACH_MSP430x11x1;
536 val = E_MSP430_MACH_MSP430x11;
540 val = E_MSP430_MACH_MSP430x12;
544 val = E_MSP430_MACH_MSP430x13;
548 val = E_MSP430_MACH_MSP430x14;
552 val = E_MSP430_MACH_MSP430x15;
556 val = E_MSP430_MACH_MSP430x16;
560 val = E_MSP430_MACH_MSP430x31;
564 val = E_MSP430_MACH_MSP430x32;
568 val = E_MSP430_MACH_MSP430x33;
572 val = E_MSP430_MACH_MSP430x41;
576 val = E_MSP430_MACH_MSP430x42;
580 val = E_MSP430_MACH_MSP430x43;
584 val = E_MSP430_MACH_MSP430x44;
588 elf_elfheader (abfd)->e_machine = EM_MSP430;
589 elf_elfheader (abfd)->e_flags &= ~EF_MSP430_MACH;
590 elf_elfheader (abfd)->e_flags |= val;
593 /* Set the right machine number. */
596 elf32_msp430_object_p (abfd)
599 int e_set = bfd_mach_msp14;
601 if (elf_elfheader (abfd)->e_machine == EM_MSP430
602 || elf_elfheader (abfd)->e_machine == EM_MSP430_OLD)
604 int e_mach = elf_elfheader (abfd)->e_flags & EF_MSP430_MACH;
609 case E_MSP430_MACH_MSP430x11:
610 e_set = bfd_mach_msp11;
613 case E_MSP430_MACH_MSP430x11x1:
614 e_set = bfd_mach_msp110;
617 case E_MSP430_MACH_MSP430x12:
618 e_set = bfd_mach_msp12;
621 case E_MSP430_MACH_MSP430x13:
622 e_set = bfd_mach_msp13;
625 case E_MSP430_MACH_MSP430x14:
626 e_set = bfd_mach_msp14;
629 case E_MSP430_MACH_MSP430x15:
630 e_set = bfd_mach_msp15;
633 case E_MSP430_MACH_MSP430x16:
634 e_set = bfd_mach_msp16;
637 case E_MSP430_MACH_MSP430x31:
638 e_set = bfd_mach_msp31;
641 case E_MSP430_MACH_MSP430x32:
642 e_set = bfd_mach_msp32;
645 case E_MSP430_MACH_MSP430x33:
646 e_set = bfd_mach_msp33;
649 case E_MSP430_MACH_MSP430x41:
650 e_set = bfd_mach_msp41;
653 case E_MSP430_MACH_MSP430x42:
654 e_set = bfd_mach_msp42;
657 case E_MSP430_MACH_MSP430x43:
658 e_set = bfd_mach_msp43;
661 case E_MSP430_MACH_MSP430x44:
662 e_set = bfd_mach_msp44;
667 return bfd_default_set_arch_mach (abfd, bfd_arch_msp430, e_set);
671 elf32_msp430_post_process_headers (abfd, link_info)
673 struct bfd_link_info *link_info ATTRIBUTE_UNUSED;
675 Elf_Internal_Ehdr *i_ehdrp; /* ELF file header, internal form. */
677 i_ehdrp = elf_elfheader (abfd);
679 #ifndef ELFOSABI_STANDALONE
680 #define ELFOSABI_STANDALONE 255
683 i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_STANDALONE;
687 #define ELF_ARCH bfd_arch_msp430
688 #define ELF_MACHINE_CODE EM_MSP430
689 #define ELF_MACHINE_ALT1 EM_MSP430_OLD
690 #define ELF_MAXPAGESIZE 1
692 #define TARGET_LITTLE_SYM bfd_elf32_msp430_vec
693 #define TARGET_LITTLE_NAME "elf32-msp430"
695 #define elf_info_to_howto msp430_info_to_howto_rela
696 #define elf_info_to_howto_rel NULL
697 #define elf_backend_relocate_section elf32_msp430_relocate_section
698 #define elf_backend_gc_mark_hook elf32_msp430_gc_mark_hook
699 #define elf_backend_gc_sweep_hook elf32_msp430_gc_sweep_hook
700 #define elf_backend_check_relocs elf32_msp430_check_relocs
701 #define elf_backend_can_gc_sections 1
702 #define elf_backend_final_write_processing bfd_elf_msp430_final_write_processing
703 #define elf_backend_object_p elf32_msp430_object_p
704 #define elf_backend_post_process_headers elf32_msp430_post_process_headers
706 #include "elf32-target.h"