159024Sobrien/* SPARC-specific support for 32-bit ELF
2130561Sobrien   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
3218822Sdim   2003, 2004, 2005, 2007 Free Software Foundation, Inc.
459024Sobrien
5130561Sobrien   This file is part of BFD, the Binary File Descriptor library.
659024Sobrien
7130561Sobrien   This program is free software; you can redistribute it and/or modify
8130561Sobrien   it under the terms of the GNU General Public License as published by
9130561Sobrien   the Free Software Foundation; either version 2 of the License, or
10130561Sobrien   (at your option) any later version.
1159024Sobrien
12130561Sobrien   This program is distributed in the hope that it will be useful,
13130561Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
14130561Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15130561Sobrien   GNU General Public License for more details.
1659024Sobrien
17130561Sobrien   You should have received a copy of the GNU General Public License
18130561Sobrien   along with this program; if not, write to the Free Software
19218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2059024Sobrien
21218822Sdim#include "sysdep.h"
2259024Sobrien#include "bfd.h"
2359024Sobrien#include "bfdlink.h"
2459024Sobrien#include "libbfd.h"
2559024Sobrien#include "elf-bfd.h"
2659024Sobrien#include "elf/sparc.h"
2777298Sobrien#include "opcode/sparc.h"
28218822Sdim#include "elfxx-sparc.h"
29218822Sdim#include "elf-vxworks.h"
3059024Sobrien
31130561Sobrien/* Support for core dump NOTE sections.  */
32130561Sobrien
33130561Sobrienstatic bfd_boolean
34130561Sobrienelf32_sparc_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
35130561Sobrien{
36130561Sobrien  switch (note->descsz)
37130561Sobrien    {
38130561Sobrien    default:
39130561Sobrien      return FALSE;
40130561Sobrien
41130561Sobrien    case 260:			/* Solaris prpsinfo_t.  */
42130561Sobrien      elf_tdata (abfd)->core_program
43130561Sobrien	= _bfd_elfcore_strndup (abfd, note->descdata + 84, 16);
44130561Sobrien      elf_tdata (abfd)->core_command
45130561Sobrien	= _bfd_elfcore_strndup (abfd, note->descdata + 100, 80);
46130561Sobrien      break;
47130561Sobrien
48130561Sobrien    case 336:			/* Solaris psinfo_t.  */
49130561Sobrien      elf_tdata (abfd)->core_program
50130561Sobrien	= _bfd_elfcore_strndup (abfd, note->descdata + 88, 16);
51130561Sobrien      elf_tdata (abfd)->core_command
52130561Sobrien	= _bfd_elfcore_strndup (abfd, note->descdata + 104, 80);
53130561Sobrien      break;
54130561Sobrien    }
55130561Sobrien
56130561Sobrien  return TRUE;
57130561Sobrien}
58130561Sobrien
5959024Sobrien/* Functions for dealing with the e_flags field.
6059024Sobrien
6159024Sobrien   We don't define set_private_flags or copy_private_bfd_data because
6259024Sobrien   the only currently defined values are based on the bfd mach number,
6359024Sobrien   so we use the latter instead and defer setting e_flags until the
6459024Sobrien   file is written out.  */
6559024Sobrien
6659024Sobrien/* Merge backend specific data from an object file to the output
6759024Sobrien   object file when linking.  */
6859024Sobrien
69130561Sobrienstatic bfd_boolean
70218822Sdimelf32_sparc_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
7159024Sobrien{
72130561Sobrien  bfd_boolean error;
73218822Sdim  unsigned long ibfd_mach;
7460484Sobrien  /* FIXME: This should not be static.  */
7560484Sobrien  static unsigned long previous_ibfd_e_flags = (unsigned long) -1;
7659024Sobrien
7759024Sobrien  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
7859024Sobrien      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
79130561Sobrien    return TRUE;
8059024Sobrien
81130561Sobrien  error = FALSE;
8259024Sobrien
83218822Sdim  ibfd_mach = bfd_get_mach (ibfd);
84218822Sdim  if (bfd_mach_sparc_64bit_p (ibfd_mach))
8559024Sobrien    {
86130561Sobrien      error = TRUE;
8759024Sobrien      (*_bfd_error_handler)
88218822Sdim	(_("%B: compiled for a 64 bit system and target is 32 bit"), ibfd);
8959024Sobrien    }
9060484Sobrien  else if ((ibfd->flags & DYNAMIC) == 0)
9160484Sobrien    {
92218822Sdim      if (bfd_get_mach (obfd) < ibfd_mach)
93218822Sdim	bfd_set_arch_mach (obfd, bfd_arch_sparc, ibfd_mach);
9460484Sobrien    }
9559024Sobrien
9660484Sobrien  if (((elf_elfheader (ibfd)->e_flags & EF_SPARC_LEDATA)
9760484Sobrien       != previous_ibfd_e_flags)
9860484Sobrien      && previous_ibfd_e_flags != (unsigned long) -1)
9960484Sobrien    {
10060484Sobrien      (*_bfd_error_handler)
101218822Sdim	(_("%B: linking little endian files with big endian files"), ibfd);
102130561Sobrien      error = TRUE;
10360484Sobrien    }
10460484Sobrien  previous_ibfd_e_flags = elf_elfheader (ibfd)->e_flags & EF_SPARC_LEDATA;
10560484Sobrien
10659024Sobrien  if (error)
10759024Sobrien    {
10859024Sobrien      bfd_set_error (bfd_error_bad_value);
109130561Sobrien      return FALSE;
11059024Sobrien    }
11159024Sobrien
112130561Sobrien  return TRUE;
11359024Sobrien}
11459024Sobrien
11559024Sobrien/* The final processing done just before writing out the object file.
11659024Sobrien   We need to set the e_machine field appropriately.  */
11759024Sobrien
11859024Sobrienstatic void
119218822Sdimelf32_sparc_final_write_processing (bfd *abfd,
120218822Sdim				    bfd_boolean linker ATTRIBUTE_UNUSED)
12159024Sobrien{
12259024Sobrien  switch (bfd_get_mach (abfd))
12359024Sobrien    {
12459024Sobrien    case bfd_mach_sparc :
125218822Sdim    case bfd_mach_sparc_sparclet :
126218822Sdim    case bfd_mach_sparc_sparclite :
12759024Sobrien      break; /* nothing to do */
12859024Sobrien    case bfd_mach_sparc_v8plus :
12959024Sobrien      elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS;
13059024Sobrien      elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK;
13159024Sobrien      elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS;
13259024Sobrien      break;
13359024Sobrien    case bfd_mach_sparc_v8plusa :
13459024Sobrien      elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS;
13559024Sobrien      elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK;
13659024Sobrien      elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS | EF_SPARC_SUN_US1;
13759024Sobrien      break;
13877298Sobrien    case bfd_mach_sparc_v8plusb :
13977298Sobrien      elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS;
14077298Sobrien      elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK;
14177298Sobrien      elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS | EF_SPARC_SUN_US1
14277298Sobrien				       | EF_SPARC_SUN_US3;
14377298Sobrien      break;
14460484Sobrien    case bfd_mach_sparc_sparclite_le :
14560484Sobrien      elf_elfheader (abfd)->e_flags |= EF_SPARC_LEDATA;
14660484Sobrien      break;
14759024Sobrien    default :
14859024Sobrien      abort ();
14960484Sobrien      break;
15059024Sobrien    }
15159024Sobrien}
15289857Sobrien
15389857Sobrienstatic enum elf_reloc_type_class
154218822Sdimelf32_sparc_reloc_type_class (const Elf_Internal_Rela *rela)
15589857Sobrien{
15689857Sobrien  switch ((int) ELF32_R_TYPE (rela->r_info))
15789857Sobrien    {
15889857Sobrien    case R_SPARC_RELATIVE:
15989857Sobrien      return reloc_class_relative;
16089857Sobrien    case R_SPARC_JMP_SLOT:
16189857Sobrien      return reloc_class_plt;
16289857Sobrien    case R_SPARC_COPY:
16389857Sobrien      return reloc_class_copy;
16489857Sobrien    default:
16589857Sobrien      return reloc_class_normal;
16689857Sobrien    }
16789857Sobrien}
168218822Sdim
16959024Sobrien#define TARGET_BIG_SYM	bfd_elf32_sparc_vec
17059024Sobrien#define TARGET_BIG_NAME	"elf32-sparc"
17159024Sobrien#define ELF_ARCH	bfd_arch_sparc
17259024Sobrien#define ELF_MACHINE_CODE EM_SPARC
17359024Sobrien#define ELF_MACHINE_ALT1 EM_SPARC32PLUS
17459024Sobrien#define ELF_MAXPAGESIZE 0x10000
175218822Sdim#define ELF_COMMONPAGESIZE 0x2000
17659024Sobrien
177218822Sdim#define bfd_elf32_bfd_merge_private_bfd_data \
178218822Sdim					elf32_sparc_merge_private_bfd_data
179218822Sdim#define elf_backend_final_write_processing \
180218822Sdim					elf32_sparc_final_write_processing
181218822Sdim#define elf_backend_grok_psinfo		elf32_sparc_grok_psinfo
182218822Sdim#define elf_backend_reloc_type_class	elf32_sparc_reloc_type_class
183218822Sdim
184218822Sdim#define elf_info_to_howto		_bfd_sparc_elf_info_to_howto
185218822Sdim#define bfd_elf32_bfd_reloc_type_lookup	_bfd_sparc_elf_reloc_type_lookup
186218822Sdim#define bfd_elf32_bfd_reloc_name_lookup \
187218822Sdim  _bfd_sparc_elf_reloc_name_lookup
188130561Sobrien#define bfd_elf32_bfd_link_hash_table_create \
189218822Sdim					_bfd_sparc_elf_link_hash_table_create
190218822Sdim#define bfd_elf32_bfd_relax_section	_bfd_sparc_elf_relax_section
191218822Sdim#define bfd_elf32_new_section_hook	_bfd_sparc_elf_new_section_hook
192130561Sobrien#define elf_backend_copy_indirect_symbol \
193218822Sdim					_bfd_sparc_elf_copy_indirect_symbol
19459024Sobrien#define elf_backend_create_dynamic_sections \
195218822Sdim					_bfd_sparc_elf_create_dynamic_sections
196218822Sdim#define elf_backend_check_relocs	_bfd_sparc_elf_check_relocs
19759024Sobrien#define elf_backend_adjust_dynamic_symbol \
198218822Sdim					_bfd_sparc_elf_adjust_dynamic_symbol
199218822Sdim#define elf_backend_omit_section_dynsym	_bfd_sparc_elf_omit_section_dynsym
20059024Sobrien#define elf_backend_size_dynamic_sections \
201218822Sdim					_bfd_sparc_elf_size_dynamic_sections
202218822Sdim#define elf_backend_relocate_section	_bfd_sparc_elf_relocate_section
20359024Sobrien#define elf_backend_finish_dynamic_symbol \
204218822Sdim					_bfd_sparc_elf_finish_dynamic_symbol
20559024Sobrien#define elf_backend_finish_dynamic_sections \
206218822Sdim					_bfd_sparc_elf_finish_dynamic_sections
207218822Sdim#define bfd_elf32_mkobject		_bfd_sparc_elf_mkobject
208218822Sdim#define elf_backend_object_p		_bfd_sparc_elf_object_p
209218822Sdim#define elf_backend_gc_mark_hook	_bfd_sparc_elf_gc_mark_hook
210218822Sdim#define elf_backend_gc_sweep_hook       _bfd_sparc_elf_gc_sweep_hook
211218822Sdim#define elf_backend_plt_sym_val		_bfd_sparc_elf_plt_sym_val
212218822Sdim#define elf_backend_init_index_section	_bfd_elf_init_1_index_section
21360484Sobrien
21460484Sobrien#define elf_backend_can_gc_sections 1
215130561Sobrien#define elf_backend_can_refcount 1
21659024Sobrien#define elf_backend_want_got_plt 0
21759024Sobrien#define elf_backend_plt_readonly 0
21859024Sobrien#define elf_backend_want_plt_sym 1
21960484Sobrien#define elf_backend_got_header_size 4
220130561Sobrien#define elf_backend_rela_normal 1
22159024Sobrien
22259024Sobrien#include "elf32-target.h"
223218822Sdim
224218822Sdim/* A wrapper around _bfd_sparc_elf_link_hash_table_create that identifies
225218822Sdim   the target system as VxWorks.  */
226218822Sdim
227218822Sdimstatic struct bfd_link_hash_table *
228218822Sdimelf32_sparc_vxworks_link_hash_table_create (bfd *abfd)
229218822Sdim{
230218822Sdim  struct bfd_link_hash_table *ret;
231218822Sdim
232218822Sdim  ret = _bfd_sparc_elf_link_hash_table_create (abfd);
233218822Sdim  if (ret)
234218822Sdim    {
235218822Sdim      struct _bfd_sparc_elf_link_hash_table *htab;
236218822Sdim
237218822Sdim      htab = (struct _bfd_sparc_elf_link_hash_table *) ret;
238218822Sdim      htab->is_vxworks = 1;
239218822Sdim    }
240218822Sdim  return ret;
241218822Sdim}
242218822Sdim
243218822Sdim/* A final_write_processing hook that does both the SPARC- and VxWorks-
244218822Sdim   specific handling.  */
245218822Sdim
246218822Sdimstatic void
247218822Sdimelf32_sparc_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker)
248218822Sdim{
249218822Sdim  elf32_sparc_final_write_processing (abfd, linker);
250218822Sdim  elf_vxworks_final_write_processing (abfd, linker);
251218822Sdim}
252218822Sdim
253218822Sdim#undef TARGET_BIG_SYM
254218822Sdim#define TARGET_BIG_SYM	bfd_elf32_sparc_vxworks_vec
255218822Sdim#undef TARGET_BIG_NAME
256218822Sdim#define TARGET_BIG_NAME	"elf32-sparc-vxworks"
257218822Sdim
258218822Sdim#undef ELF_MINPAGESIZE
259218822Sdim#define ELF_MINPAGESIZE	0x1000
260218822Sdim
261218822Sdim#undef bfd_elf32_bfd_link_hash_table_create
262218822Sdim#define bfd_elf32_bfd_link_hash_table_create \
263218822Sdim  elf32_sparc_vxworks_link_hash_table_create
264218822Sdim
265218822Sdim#undef elf_backend_want_got_plt
266218822Sdim#define elf_backend_want_got_plt		1
267218822Sdim#undef elf_backend_plt_readonly
268218822Sdim#define elf_backend_plt_readonly		1
269218822Sdim#undef elf_backend_got_header_size
270218822Sdim#define elf_backend_got_header_size		12
271218822Sdim#undef elf_backend_add_symbol_hook
272218822Sdim#define elf_backend_add_symbol_hook \
273218822Sdim  elf_vxworks_add_symbol_hook
274218822Sdim#undef elf_backend_link_output_symbol_hook
275218822Sdim#define elf_backend_link_output_symbol_hook \
276218822Sdim  elf_vxworks_link_output_symbol_hook
277218822Sdim#undef elf_backend_emit_relocs
278218822Sdim#define elf_backend_emit_relocs \
279218822Sdim  elf_vxworks_emit_relocs
280218822Sdim#undef elf_backend_final_write_processing
281218822Sdim#define elf_backend_final_write_processing \
282218822Sdim  elf32_sparc_vxworks_final_write_processing
283218822Sdim
284218822Sdim#undef elf32_bed
285218822Sdim#define elf32_bed				sparc_elf_vxworks_bed
286218822Sdim
287218822Sdim#include "elf32-target.h"
288