1 /* MSP430-specific support for 32-bit ELF
2 Copyright (C) 2002 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
->relocateable
)
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 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
462 while (h
->root
.type
== bfd_link_hash_indirect
463 || h
->root
.type
== bfd_link_hash_warning
)
464 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
466 name
= h
->root
.root
.string
;
468 if (h
->root
.type
== bfd_link_hash_defined
469 || h
->root
.type
== bfd_link_hash_defweak
)
471 sec
= h
->root
.u
.def
.section
;
472 relocation
= (h
->root
.u
.def
.value
473 + sec
->output_section
->vma
+ sec
->output_offset
);
475 else if (h
->root
.type
== bfd_link_hash_undefweak
)
481 if (!((*info
->callbacks
->undefined_symbol
)
482 (info
, h
->root
.root
.string
, input_bfd
,
483 input_section
, rel
->r_offset
, TRUE
)))
489 r
= msp430_final_link_relocate (howto
, input_bfd
, input_section
,
490 contents
, rel
, relocation
);
492 if (r
!= bfd_reloc_ok
)
494 const char *msg
= (const char *) NULL
;
498 case bfd_reloc_overflow
:
499 r
= info
->callbacks
->reloc_overflow
500 (info
, name
, howto
->name
, (bfd_vma
) 0,
501 input_bfd
, input_section
, rel
->r_offset
);
504 case bfd_reloc_undefined
:
505 r
= info
->callbacks
->undefined_symbol
506 (info
, name
, input_bfd
, input_section
, rel
->r_offset
, TRUE
);
509 case bfd_reloc_outofrange
:
510 msg
= _("internal error: out of range error");
513 case bfd_reloc_notsupported
:
514 msg
= _("internal error: unsupported relocation error");
517 case bfd_reloc_dangerous
:
518 msg
= _("internal error: dangerous relocation");
522 msg
= _("internal error: unknown error");
527 r
= info
->callbacks
->warning
528 (info
, msg
, name
, input_bfd
, input_section
, rel
->r_offset
);
539 /* The final processing done just before writing out a MSP430 ELF object
540 file. This gets the MSP430 architecture right based on the machine
544 bfd_elf_msp430_final_write_processing (abfd
, linker
)
546 bfd_boolean linker ATTRIBUTE_UNUSED
;
550 switch (bfd_get_mach (abfd
))
554 val
= E_MSP430_MACH_MSP430x12
;
557 case bfd_mach_msp110
:
558 val
= E_MSP430_MACH_MSP430x11x1
;
562 val
= E_MSP430_MACH_MSP430x11
;
566 val
= E_MSP430_MACH_MSP430x13
;
570 val
= E_MSP430_MACH_MSP430x14
;
574 val
= E_MSP430_MACH_MSP430x41
;
578 val
= E_MSP430_MACH_MSP430x43
;
582 val
= E_MSP430_MACH_MSP430x44
;
586 val
= E_MSP430_MACH_MSP430x31
;
590 val
= E_MSP430_MACH_MSP430x32
;
594 val
= E_MSP430_MACH_MSP430x33
;
598 val
= E_MSP430_MACH_MSP430x15
;
602 val
= E_MSP430_MACH_MSP430x16
;
606 elf_elfheader (abfd
)->e_machine
= EM_MSP430
;
607 elf_elfheader (abfd
)->e_flags
&= ~EF_MSP430_MACH
;
608 elf_elfheader (abfd
)->e_flags
|= val
;
611 /* Set the right machine number. */
614 elf32_msp430_object_p (abfd
)
617 int e_set
= bfd_mach_msp14
;
619 if (elf_elfheader (abfd
)->e_machine
== EM_MSP430
620 || elf_elfheader (abfd
)->e_machine
== EM_MSP430_OLD
)
622 int e_mach
= elf_elfheader (abfd
)->e_flags
& EF_MSP430_MACH
;
627 case E_MSP430_MACH_MSP430x12
:
628 e_set
= bfd_mach_msp12
;
631 case E_MSP430_MACH_MSP430x11
:
632 e_set
= bfd_mach_msp11
;
635 case E_MSP430_MACH_MSP430x11x1
:
636 e_set
= bfd_mach_msp110
;
639 case E_MSP430_MACH_MSP430x13
:
640 e_set
= bfd_mach_msp13
;
643 case E_MSP430_MACH_MSP430x14
:
644 e_set
= bfd_mach_msp14
;
647 case E_MSP430_MACH_MSP430x41
:
648 e_set
= bfd_mach_msp41
;
651 case E_MSP430_MACH_MSP430x31
:
652 e_set
= bfd_mach_msp31
;
655 case E_MSP430_MACH_MSP430x32
:
656 e_set
= bfd_mach_msp32
;
659 case E_MSP430_MACH_MSP430x33
:
660 e_set
= bfd_mach_msp33
;
663 case E_MSP430_MACH_MSP430x43
:
664 e_set
= bfd_mach_msp43
;
667 case E_MSP430_MACH_MSP430x44
:
668 e_set
= bfd_mach_msp44
;
671 case E_MSP430_MACH_MSP430x15
:
672 e_set
= bfd_mach_msp15
;
675 case E_MSP430_MACH_MSP430x16
:
676 e_set
= bfd_mach_msp16
;
681 return bfd_default_set_arch_mach (abfd
, bfd_arch_msp430
, e_set
);
685 elf32_msp430_post_process_headers (abfd
, link_info
)
687 struct bfd_link_info
*link_info ATTRIBUTE_UNUSED
;
689 Elf_Internal_Ehdr
*i_ehdrp
; /* ELF file header, internal form. */
691 i_ehdrp
= elf_elfheader (abfd
);
693 #ifndef ELFOSABI_STANDALONE
694 #define ELFOSABI_STANDALONE 255
697 i_ehdrp
->e_ident
[EI_OSABI
] = ELFOSABI_STANDALONE
;
701 #define ELF_ARCH bfd_arch_msp430
702 #define ELF_MACHINE_CODE EM_MSP430
703 #define ELF_MACHINE_ALT1 EM_MSP430_OLD
704 #define ELF_MAXPAGESIZE 1
706 #define TARGET_LITTLE_SYM bfd_elf32_msp430_vec
707 #define TARGET_LITTLE_NAME "elf32-msp430"
709 #define elf_info_to_howto msp430_info_to_howto_rela
710 #define elf_info_to_howto_rel NULL
711 #define elf_backend_relocate_section elf32_msp430_relocate_section
712 #define elf_backend_gc_mark_hook elf32_msp430_gc_mark_hook
713 #define elf_backend_gc_sweep_hook elf32_msp430_gc_sweep_hook
714 #define elf_backend_check_relocs elf32_msp430_check_relocs
715 #define elf_backend_can_gc_sections 1
716 #define elf_backend_final_write_processing bfd_elf_msp430_final_write_processing
717 #define elf_backend_object_p elf32_msp430_object_p
718 #define elf_backend_post_process_headers elf32_msp430_post_process_headers
720 #include "elf32-target.h"