1d2201f2fSdrahn /* SuperH SH64-specific support for 32-bit ELF
2*cf2f2c56Smiod Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
3d2201f2fSdrahn
4d2201f2fSdrahn This file is part of BFD, the Binary File Descriptor library.
5d2201f2fSdrahn
6d2201f2fSdrahn This program is free software; you can redistribute it and/or modify
7d2201f2fSdrahn it under the terms of the GNU General Public License as published by
8d2201f2fSdrahn the Free Software Foundation; either version 2 of the License, or
9d2201f2fSdrahn (at your option) any later version.
10d2201f2fSdrahn
11d2201f2fSdrahn This program is distributed in the hope that it will be useful,
12d2201f2fSdrahn but WITHOUT ANY WARRANTY; without even the implied warranty of
13d2201f2fSdrahn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14d2201f2fSdrahn GNU General Public License for more details.
15d2201f2fSdrahn
16d2201f2fSdrahn You should have received a copy of the GNU General Public License
17d2201f2fSdrahn along with this program; if not, write to the Free Software
18d2201f2fSdrahn Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19d2201f2fSdrahn
20d2201f2fSdrahn #define SH64_ELF
21d2201f2fSdrahn
22d2201f2fSdrahn #include "bfd.h"
23d2201f2fSdrahn #include "sysdep.h"
24d2201f2fSdrahn #include "elf-bfd.h"
25d2201f2fSdrahn #include "../opcodes/sh64-opc.h"
26d2201f2fSdrahn #include "elf32-sh64.h"
27d2201f2fSdrahn
28d2201f2fSdrahn /* Add a suffix for datalabel indirection symbols. It must not match any
29d2201f2fSdrahn other symbols; user symbols with or without version or other
30d2201f2fSdrahn decoration. It must only be used internally and not emitted by any
31d2201f2fSdrahn means. */
32d2201f2fSdrahn #define DATALABEL_SUFFIX " DL"
33d2201f2fSdrahn
34d2201f2fSdrahn /* Used to hold data for function called through bfd_map_over_sections. */
35d2201f2fSdrahn struct sh64_find_section_vma_data
36d2201f2fSdrahn {
37d2201f2fSdrahn asection *section;
38d2201f2fSdrahn bfd_vma addr;
39d2201f2fSdrahn };
40d2201f2fSdrahn
41d2201f2fSdrahn static bfd_boolean sh64_elf_new_section_hook
42*cf2f2c56Smiod (bfd *, asection *);
43d2201f2fSdrahn static bfd_boolean sh64_elf_copy_private_data
44*cf2f2c56Smiod (bfd *, bfd *);
45d2201f2fSdrahn static bfd_boolean sh64_elf_merge_private_data
46*cf2f2c56Smiod (bfd *, bfd *);
47d2201f2fSdrahn static bfd_boolean sh64_elf_fake_sections
48*cf2f2c56Smiod (bfd *, Elf_Internal_Shdr *, asection *);
49d2201f2fSdrahn static bfd_boolean sh64_elf_set_private_flags
50*cf2f2c56Smiod (bfd *, flagword);
51d2201f2fSdrahn static bfd_boolean sh64_elf_set_mach_from_flags
52*cf2f2c56Smiod (bfd *);
53d2201f2fSdrahn static bfd_boolean shmedia_prepare_reloc
54*cf2f2c56Smiod (struct bfd_link_info *, bfd *, asection *, bfd_byte *,
55*cf2f2c56Smiod const Elf_Internal_Rela *, bfd_vma *);
56d2201f2fSdrahn static int sh64_elf_get_symbol_type
57*cf2f2c56Smiod (Elf_Internal_Sym *, int);
58d2201f2fSdrahn static bfd_boolean sh64_elf_add_symbol_hook
59*cf2f2c56Smiod (bfd *, struct bfd_link_info *, Elf_Internal_Sym *, const char **,
60*cf2f2c56Smiod flagword *, asection **, bfd_vma *);
61d2201f2fSdrahn static bfd_boolean sh64_elf_link_output_symbol_hook
62*cf2f2c56Smiod (struct bfd_link_info *, const char *, Elf_Internal_Sym *, asection *,
63*cf2f2c56Smiod struct elf_link_hash_entry *);
64d2201f2fSdrahn static bfd_boolean sh64_backend_section_from_shdr
65*cf2f2c56Smiod (bfd *, Elf_Internal_Shdr *, const char *);
66d2201f2fSdrahn static void sh64_elf_final_write_processing
67*cf2f2c56Smiod (bfd *, bfd_boolean);
68d2201f2fSdrahn static bfd_boolean sh64_bfd_elf_copy_private_section_data
69*cf2f2c56Smiod (bfd *, asection *, bfd *, asection *);
70d2201f2fSdrahn static void sh64_find_section_for_address
71*cf2f2c56Smiod (bfd *, asection *, void *);
72d2201f2fSdrahn
73d2201f2fSdrahn /* Let elf32-sh.c handle the "bfd_" definitions, so we only have to
74d2201f2fSdrahn intrude with an #ifndef around the function definition. */
75d2201f2fSdrahn #define sh_elf_copy_private_data sh64_elf_copy_private_data
76d2201f2fSdrahn #define sh_elf_merge_private_data sh64_elf_merge_private_data
77d2201f2fSdrahn #define sh_elf_set_private_flags sh64_elf_set_private_flags
78d2201f2fSdrahn /* Typo in elf32-sh.c (and unlinear name). */
79d2201f2fSdrahn #define bfd_elf32_bfd_set_private_flags sh64_elf_set_private_flags
80d2201f2fSdrahn #define sh_elf_set_mach_from_flags sh64_elf_set_mach_from_flags
81d2201f2fSdrahn
82d2201f2fSdrahn #define elf_backend_sign_extend_vma 1
83d2201f2fSdrahn #define elf_backend_fake_sections sh64_elf_fake_sections
84d2201f2fSdrahn #define elf_backend_get_symbol_type sh64_elf_get_symbol_type
85d2201f2fSdrahn #define elf_backend_add_symbol_hook sh64_elf_add_symbol_hook
86d2201f2fSdrahn #define elf_backend_link_output_symbol_hook \
87d2201f2fSdrahn sh64_elf_link_output_symbol_hook
88*cf2f2c56Smiod #define elf_backend_merge_symbol_attribute sh64_elf_merge_symbol_attribute
89d2201f2fSdrahn #define elf_backend_final_write_processing sh64_elf_final_write_processing
90d2201f2fSdrahn #define elf_backend_section_from_shdr sh64_backend_section_from_shdr
91*cf2f2c56Smiod #define elf_backend_special_sections sh64_elf_special_sections
92d2201f2fSdrahn
93d2201f2fSdrahn #define bfd_elf32_new_section_hook sh64_elf_new_section_hook
94d2201f2fSdrahn
95d2201f2fSdrahn /* For objcopy, we need to set up sh64_elf_section_data (asection *) from
96d2201f2fSdrahn incoming section flags. This is otherwise done in sh64elf.em when
97d2201f2fSdrahn linking or tc-sh64.c when assembling. */
98d2201f2fSdrahn #define bfd_elf32_bfd_copy_private_section_data \
99d2201f2fSdrahn sh64_bfd_elf_copy_private_section_data
100d2201f2fSdrahn
101d2201f2fSdrahn /* This COFF-only function (only compiled with COFF support, making
102d2201f2fSdrahn ELF-only chains problematic) returns TRUE early for SH4, so let's just
103d2201f2fSdrahn define it TRUE here. */
104d2201f2fSdrahn #define _bfd_sh_align_load_span(a,b,c,d,e,f,g,h,i,j) TRUE
105d2201f2fSdrahn
106d2201f2fSdrahn #define GOT_BIAS (-((long)-32768))
107d2201f2fSdrahn #define INCLUDE_SHMEDIA
108d2201f2fSdrahn #include "elf32-sh.c"
109d2201f2fSdrahn
110d2201f2fSdrahn /* Tack some extra info on struct bfd_elf_section_data. */
111d2201f2fSdrahn
112d2201f2fSdrahn static bfd_boolean
sh64_elf_new_section_hook(bfd * abfd,asection * sec)113*cf2f2c56Smiod sh64_elf_new_section_hook (bfd *abfd, asection *sec)
114d2201f2fSdrahn {
115d2201f2fSdrahn struct _sh64_elf_section_data *sdata;
116d2201f2fSdrahn bfd_size_type amt = sizeof (*sdata);
117d2201f2fSdrahn
118d2201f2fSdrahn sdata = (struct _sh64_elf_section_data *) bfd_zalloc (abfd, amt);
119d2201f2fSdrahn if (sdata == NULL)
120d2201f2fSdrahn return FALSE;
121*cf2f2c56Smiod sec->used_by_bfd = sdata;
122d2201f2fSdrahn
123d2201f2fSdrahn return _bfd_elf_new_section_hook (abfd, sec);
124d2201f2fSdrahn }
125d2201f2fSdrahn
126d2201f2fSdrahn /* Set the SHF_SH5_ISA32 flag for ISA SHmedia code sections, and pass
127d2201f2fSdrahn through SHT_SH5_CR_SORTED on a sorted .cranges section. */
128d2201f2fSdrahn
129d2201f2fSdrahn bfd_boolean
sh64_elf_fake_sections(bfd * output_bfd ATTRIBUTE_UNUSED,Elf_Internal_Shdr * elf_section_hdr,asection * asect)130*cf2f2c56Smiod sh64_elf_fake_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
131*cf2f2c56Smiod Elf_Internal_Shdr *elf_section_hdr,
132*cf2f2c56Smiod asection *asect)
133d2201f2fSdrahn {
134d2201f2fSdrahn if (sh64_elf_section_data (asect)->sh64_info != NULL)
135d2201f2fSdrahn elf_section_hdr->sh_flags
136d2201f2fSdrahn |= sh64_elf_section_data (asect)->sh64_info->contents_flags;
137d2201f2fSdrahn
138d2201f2fSdrahn /* If this section has the SEC_SORT_ENTRIES flag set, it is a sorted
139d2201f2fSdrahn .cranges section passing through objcopy. */
140d2201f2fSdrahn if ((bfd_get_section_flags (output_bfd, asect) & SEC_SORT_ENTRIES) != 0
141d2201f2fSdrahn && strcmp (bfd_get_section_name (output_bfd, asect),
142d2201f2fSdrahn SH64_CRANGES_SECTION_NAME) == 0)
143d2201f2fSdrahn elf_section_hdr->sh_type = SHT_SH5_CR_SORTED;
144d2201f2fSdrahn
145d2201f2fSdrahn return TRUE;
146d2201f2fSdrahn }
147d2201f2fSdrahn
148d2201f2fSdrahn static bfd_boolean
sh64_elf_set_mach_from_flags(bfd * abfd)149*cf2f2c56Smiod sh64_elf_set_mach_from_flags (bfd *abfd)
150d2201f2fSdrahn {
151d2201f2fSdrahn flagword flags = elf_elfheader (abfd)->e_flags;
152d2201f2fSdrahn asection *cranges;
153d2201f2fSdrahn
154d2201f2fSdrahn switch (flags & EF_SH_MACH_MASK)
155d2201f2fSdrahn {
156d2201f2fSdrahn case EF_SH5:
157d2201f2fSdrahn /* These are fit to execute on SH5. Just one but keep the switch
158d2201f2fSdrahn construct to make additions easy. */
159d2201f2fSdrahn bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh5);
160d2201f2fSdrahn break;
161d2201f2fSdrahn
162d2201f2fSdrahn default:
163d2201f2fSdrahn bfd_set_error (bfd_error_wrong_format);
164d2201f2fSdrahn return FALSE;
165d2201f2fSdrahn }
166d2201f2fSdrahn
167d2201f2fSdrahn /* We also need to set SEC_DEBUGGING on an incoming .cranges section.
168d2201f2fSdrahn We could have used elf_backend_section_flags if it had given us the
169d2201f2fSdrahn section name; the bfd_section member in the header argument is not
170d2201f2fSdrahn set at the point of the call. FIXME: Find out whether that is by
171d2201f2fSdrahn undocumented design or a bug. */
172d2201f2fSdrahn cranges = bfd_get_section_by_name (abfd, SH64_CRANGES_SECTION_NAME);
173d2201f2fSdrahn if (cranges != NULL
174d2201f2fSdrahn && ! bfd_set_section_flags (abfd, cranges,
175d2201f2fSdrahn bfd_get_section_flags (abfd, cranges)
176d2201f2fSdrahn | SEC_DEBUGGING))
177d2201f2fSdrahn return FALSE;
178d2201f2fSdrahn
179d2201f2fSdrahn return TRUE;
180d2201f2fSdrahn }
181d2201f2fSdrahn
182d2201f2fSdrahn static bfd_boolean
sh64_elf_copy_private_data(bfd * ibfd,bfd * obfd)183*cf2f2c56Smiod sh64_elf_copy_private_data (bfd * ibfd, bfd * obfd)
184d2201f2fSdrahn {
185d2201f2fSdrahn if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
186d2201f2fSdrahn || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
187d2201f2fSdrahn return TRUE;
188d2201f2fSdrahn
189d2201f2fSdrahn BFD_ASSERT (!elf_flags_init (obfd)
190d2201f2fSdrahn || (elf_elfheader (obfd)->e_flags
191d2201f2fSdrahn == elf_elfheader (ibfd)->e_flags));
192d2201f2fSdrahn
193d2201f2fSdrahn elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
194d2201f2fSdrahn return TRUE;
195d2201f2fSdrahn }
196d2201f2fSdrahn
197d2201f2fSdrahn static bfd_boolean
sh64_elf_merge_private_data(bfd * ibfd,bfd * obfd)198*cf2f2c56Smiod sh64_elf_merge_private_data (bfd *ibfd, bfd *obfd)
199d2201f2fSdrahn {
200d2201f2fSdrahn flagword old_flags, new_flags;
201d2201f2fSdrahn
202d2201f2fSdrahn if (! _bfd_generic_verify_endian_match (ibfd, obfd))
203d2201f2fSdrahn return FALSE;
204d2201f2fSdrahn
205d2201f2fSdrahn if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
206d2201f2fSdrahn || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
207d2201f2fSdrahn return TRUE;
208d2201f2fSdrahn
209d2201f2fSdrahn if (bfd_get_arch_size (ibfd) != bfd_get_arch_size (obfd))
210d2201f2fSdrahn {
211d2201f2fSdrahn const char *msg;
212d2201f2fSdrahn
213d2201f2fSdrahn if (bfd_get_arch_size (ibfd) == 32
214d2201f2fSdrahn && bfd_get_arch_size (obfd) == 64)
215d2201f2fSdrahn msg = _("%s: compiled as 32-bit object and %s is 64-bit");
216d2201f2fSdrahn else if (bfd_get_arch_size (ibfd) == 64
217d2201f2fSdrahn && bfd_get_arch_size (obfd) == 32)
218d2201f2fSdrahn msg = _("%s: compiled as 64-bit object and %s is 32-bit");
219d2201f2fSdrahn else
220d2201f2fSdrahn msg = _("%s: object size does not match that of target %s");
221d2201f2fSdrahn
222d2201f2fSdrahn (*_bfd_error_handler) (msg, bfd_get_filename (ibfd),
223d2201f2fSdrahn bfd_get_filename (obfd));
224d2201f2fSdrahn bfd_set_error (bfd_error_wrong_format);
225d2201f2fSdrahn return FALSE;
226d2201f2fSdrahn }
227d2201f2fSdrahn
228d2201f2fSdrahn old_flags = elf_elfheader (obfd)->e_flags;
229d2201f2fSdrahn new_flags = elf_elfheader (ibfd)->e_flags;
230d2201f2fSdrahn if (! elf_flags_init (obfd))
231d2201f2fSdrahn {
232d2201f2fSdrahn /* This happens when ld starts out with a 'blank' output file. */
233d2201f2fSdrahn elf_flags_init (obfd) = TRUE;
234d2201f2fSdrahn elf_elfheader (obfd)->e_flags = old_flags = new_flags;
235d2201f2fSdrahn }
236d2201f2fSdrahn /* We don't allow linking in non-SH64 code. */
237d2201f2fSdrahn else if ((new_flags & EF_SH_MACH_MASK) != EF_SH5)
238d2201f2fSdrahn {
239d2201f2fSdrahn (*_bfd_error_handler)
240d2201f2fSdrahn ("%s: uses non-SH64 instructions while previous modules use SH64 instructions",
241d2201f2fSdrahn bfd_get_filename (ibfd));
242d2201f2fSdrahn bfd_set_error (bfd_error_bad_value);
243d2201f2fSdrahn return FALSE;
244d2201f2fSdrahn }
245d2201f2fSdrahn
246d2201f2fSdrahn /* I can't think of anything sane other than old_flags being EF_SH5 and
247d2201f2fSdrahn that we need to preserve that. */
248d2201f2fSdrahn elf_elfheader (obfd)->e_flags = old_flags;
249d2201f2fSdrahn return sh64_elf_set_mach_from_flags (obfd);
250d2201f2fSdrahn }
251d2201f2fSdrahn
252d2201f2fSdrahn /* Handle a SH64-specific section when reading an object file. This
253d2201f2fSdrahn is called when elfcode.h finds a section with an unknown type.
254d2201f2fSdrahn
255d2201f2fSdrahn We only recognize SHT_SH5_CR_SORTED, on the .cranges section. */
256d2201f2fSdrahn
257d2201f2fSdrahn bfd_boolean
sh64_backend_section_from_shdr(bfd * abfd,Elf_Internal_Shdr * hdr,const char * name)258*cf2f2c56Smiod sh64_backend_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr,
259*cf2f2c56Smiod const char *name)
260d2201f2fSdrahn {
261d2201f2fSdrahn flagword flags = 0;
262d2201f2fSdrahn
263d2201f2fSdrahn /* We do like MIPS with a bit switch for recognized types, and returning
264d2201f2fSdrahn FALSE for a recognized section type with an unexpected name. Right
265d2201f2fSdrahn now we only have one recognized type, but that might change. */
266d2201f2fSdrahn switch (hdr->sh_type)
267d2201f2fSdrahn {
268d2201f2fSdrahn case SHT_SH5_CR_SORTED:
269d2201f2fSdrahn if (strcmp (name, SH64_CRANGES_SECTION_NAME) != 0)
270d2201f2fSdrahn return FALSE;
271d2201f2fSdrahn
272d2201f2fSdrahn /* We set the SEC_SORT_ENTRIES flag so it can be passed on to
273d2201f2fSdrahn sh64_elf_fake_sections, keeping SHT_SH5_CR_SORTED if this object
274d2201f2fSdrahn passes through objcopy. Perhaps it is brittle; the flag can
275d2201f2fSdrahn suddenly be used by other BFD parts, but it seems not really used
276d2201f2fSdrahn anywhere at the moment. */
277d2201f2fSdrahn flags = SEC_DEBUGGING | SEC_SORT_ENTRIES;
278d2201f2fSdrahn break;
279d2201f2fSdrahn
280d2201f2fSdrahn default:
281d2201f2fSdrahn return FALSE;
282d2201f2fSdrahn }
283d2201f2fSdrahn
284d2201f2fSdrahn if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
285d2201f2fSdrahn return FALSE;
286d2201f2fSdrahn
287d2201f2fSdrahn if (flags
288d2201f2fSdrahn && ! bfd_set_section_flags (abfd, hdr->bfd_section,
289d2201f2fSdrahn bfd_get_section_flags (abfd,
290d2201f2fSdrahn hdr->bfd_section)
291d2201f2fSdrahn | flags))
292d2201f2fSdrahn return FALSE;
293d2201f2fSdrahn
294d2201f2fSdrahn return TRUE;
295d2201f2fSdrahn }
296d2201f2fSdrahn
297d2201f2fSdrahn /* In contrast to sh64_backend_section_from_shdr, this is called for all
298d2201f2fSdrahn sections, but only when copying sections, not when linking or
299d2201f2fSdrahn assembling. We need to set up the sh64_elf_section_data (asection *)
300d2201f2fSdrahn structure for the SH64 ELF section flags to be copied correctly. */
301d2201f2fSdrahn
302d2201f2fSdrahn bfd_boolean
sh64_bfd_elf_copy_private_section_data(bfd * ibfd,asection * isec,bfd * obfd,asection * osec)303*cf2f2c56Smiod sh64_bfd_elf_copy_private_section_data (bfd *ibfd, asection *isec,
304*cf2f2c56Smiod bfd *obfd, asection *osec)
305d2201f2fSdrahn {
306d2201f2fSdrahn struct sh64_section_data *sh64_sec_data;
307d2201f2fSdrahn
308d2201f2fSdrahn if (ibfd->xvec->flavour != bfd_target_elf_flavour
309d2201f2fSdrahn || obfd->xvec->flavour != bfd_target_elf_flavour)
310d2201f2fSdrahn return TRUE;
311d2201f2fSdrahn
312d2201f2fSdrahn if (! _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec))
313d2201f2fSdrahn return FALSE;
314d2201f2fSdrahn
315d2201f2fSdrahn sh64_sec_data = sh64_elf_section_data (isec)->sh64_info;
316d2201f2fSdrahn if (sh64_sec_data == NULL)
317d2201f2fSdrahn {
318d2201f2fSdrahn sh64_sec_data = bfd_zmalloc (sizeof (struct sh64_section_data));
319d2201f2fSdrahn
320d2201f2fSdrahn if (sh64_sec_data == NULL)
321d2201f2fSdrahn return FALSE;
322d2201f2fSdrahn
323d2201f2fSdrahn sh64_sec_data->contents_flags
324d2201f2fSdrahn = (elf_section_data (isec)->this_hdr.sh_flags
325d2201f2fSdrahn & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED));
326d2201f2fSdrahn
327d2201f2fSdrahn sh64_elf_section_data (osec)->sh64_info = sh64_sec_data;
328d2201f2fSdrahn }
329d2201f2fSdrahn
330d2201f2fSdrahn return TRUE;
331d2201f2fSdrahn }
332d2201f2fSdrahn
333d2201f2fSdrahn /* Function to keep SH64 specific file flags. */
334d2201f2fSdrahn
335d2201f2fSdrahn static bfd_boolean
sh64_elf_set_private_flags(bfd * abfd,flagword flags)336*cf2f2c56Smiod sh64_elf_set_private_flags (bfd *abfd, flagword flags)
337d2201f2fSdrahn {
338d2201f2fSdrahn BFD_ASSERT (! elf_flags_init (abfd)
339d2201f2fSdrahn || elf_elfheader (abfd)->e_flags == flags);
340d2201f2fSdrahn
341d2201f2fSdrahn elf_elfheader (abfd)->e_flags = flags;
342d2201f2fSdrahn elf_flags_init (abfd) = TRUE;
343d2201f2fSdrahn return sh64_elf_set_mach_from_flags (abfd);
344d2201f2fSdrahn }
345d2201f2fSdrahn
346d2201f2fSdrahn /* Called when writing out an object file to decide the type of a symbol. */
347d2201f2fSdrahn
348d2201f2fSdrahn static int
sh64_elf_get_symbol_type(Elf_Internal_Sym * elf_sym,int type)349*cf2f2c56Smiod sh64_elf_get_symbol_type (Elf_Internal_Sym *elf_sym, int type)
350d2201f2fSdrahn {
351d2201f2fSdrahn if (ELF_ST_TYPE (elf_sym->st_info) == STT_DATALABEL)
352d2201f2fSdrahn return STT_DATALABEL;
353d2201f2fSdrahn
354d2201f2fSdrahn return type;
355d2201f2fSdrahn }
356d2201f2fSdrahn
357d2201f2fSdrahn /* Hook called by the linker routine which adds symbols from an object
358d2201f2fSdrahn file. We must make indirect symbols for undefined symbols marked with
359d2201f2fSdrahn STT_DATALABEL, so relocations passing them will pick up that attribute
360d2201f2fSdrahn and neutralize STO_SH5_ISA32 found on the symbol definition.
361d2201f2fSdrahn
362d2201f2fSdrahn There is a problem, though: We want to fill in the hash-table entry for
363d2201f2fSdrahn this symbol and signal to the caller that no further processing is
364d2201f2fSdrahn needed. But we don't have the index for this hash-table entry. We
365d2201f2fSdrahn rely here on that the current entry is the first hash-entry with NULL,
366d2201f2fSdrahn which seems brittle. Also, iterating over the hash-table to find that
367d2201f2fSdrahn entry is a linear operation on the number of symbols in this input
368d2201f2fSdrahn file, and this function should take constant time, so that's not good
369d2201f2fSdrahn too. Only comfort is that DataLabel references should only be found in
370d2201f2fSdrahn hand-written assembly code and thus be rare. FIXME: Talk maintainers
371d2201f2fSdrahn into adding an option to elf_add_symbol_hook (preferably) for the index
372d2201f2fSdrahn or the hash entry, alternatively adding the index to Elf_Internal_Sym
373d2201f2fSdrahn (not so good). */
374d2201f2fSdrahn
375d2201f2fSdrahn static bfd_boolean
sh64_elf_add_symbol_hook(bfd * abfd,struct bfd_link_info * info,Elf_Internal_Sym * sym,const char ** namep,flagword * flagsp ATTRIBUTE_UNUSED,asection ** secp,bfd_vma * valp)376*cf2f2c56Smiod sh64_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
377*cf2f2c56Smiod Elf_Internal_Sym *sym, const char **namep,
378*cf2f2c56Smiod flagword *flagsp ATTRIBUTE_UNUSED,
379*cf2f2c56Smiod asection **secp, bfd_vma *valp)
380d2201f2fSdrahn {
381d2201f2fSdrahn /* We want to do this for relocatable as well as final linking. */
382d2201f2fSdrahn if (ELF_ST_TYPE (sym->st_info) == STT_DATALABEL
383*cf2f2c56Smiod && is_elf_hash_table (info->hash))
384d2201f2fSdrahn {
385d2201f2fSdrahn struct elf_link_hash_entry *h;
386d2201f2fSdrahn
387*cf2f2c56Smiod /* For relocatable links, we register the DataLabel sym in its own
388d2201f2fSdrahn right, and tweak the name when it's output. Otherwise, we make
389d2201f2fSdrahn an indirect symbol of it. */
390d2201f2fSdrahn flagword flags
391*cf2f2c56Smiod = info->relocatable || info->emitrelocations
392d2201f2fSdrahn ? BSF_GLOBAL : BSF_GLOBAL | BSF_INDIRECT;
393d2201f2fSdrahn
394d2201f2fSdrahn char *dl_name
395d2201f2fSdrahn = bfd_malloc (strlen (*namep) + sizeof (DATALABEL_SUFFIX));
396d2201f2fSdrahn struct elf_link_hash_entry ** sym_hash = elf_sym_hashes (abfd);
397d2201f2fSdrahn
398d2201f2fSdrahn BFD_ASSERT (sym_hash != NULL);
399d2201f2fSdrahn
400d2201f2fSdrahn /* Allocation may fail. */
401d2201f2fSdrahn if (dl_name == NULL)
402d2201f2fSdrahn return FALSE;
403d2201f2fSdrahn
404d2201f2fSdrahn strcpy (dl_name, *namep);
405d2201f2fSdrahn strcat (dl_name, DATALABEL_SUFFIX);
406d2201f2fSdrahn
407d2201f2fSdrahn h = (struct elf_link_hash_entry *)
408d2201f2fSdrahn bfd_link_hash_lookup (info->hash, dl_name, FALSE, FALSE, FALSE);
409d2201f2fSdrahn
410d2201f2fSdrahn if (h == NULL)
411d2201f2fSdrahn {
412d2201f2fSdrahn /* No previous datalabel symbol. Make one. */
413d2201f2fSdrahn struct bfd_link_hash_entry *bh = NULL;
414*cf2f2c56Smiod const struct elf_backend_data *bed = get_elf_backend_data (abfd);
415d2201f2fSdrahn
416d2201f2fSdrahn if (! _bfd_generic_link_add_one_symbol (info, abfd, dl_name,
417d2201f2fSdrahn flags, *secp, *valp,
418d2201f2fSdrahn *namep, FALSE,
419d2201f2fSdrahn bed->collect, &bh))
420d2201f2fSdrahn {
421d2201f2fSdrahn free (dl_name);
422d2201f2fSdrahn return FALSE;
423d2201f2fSdrahn }
424d2201f2fSdrahn
425d2201f2fSdrahn h = (struct elf_link_hash_entry *) bh;
426d2201f2fSdrahn h->elf_link_hash_flags &=~ ELF_LINK_NON_ELF;
427d2201f2fSdrahn h->type = STT_DATALABEL;
428d2201f2fSdrahn }
429d2201f2fSdrahn else
430d2201f2fSdrahn /* If a new symbol was created, it holds the allocated name.
431d2201f2fSdrahn Otherwise, we don't need it anymore and should deallocate it. */
432d2201f2fSdrahn free (dl_name);
433d2201f2fSdrahn
434d2201f2fSdrahn if (h->type != STT_DATALABEL
435*cf2f2c56Smiod || ((info->relocatable || info->emitrelocations)
436d2201f2fSdrahn && h->root.type != bfd_link_hash_undefined)
437*cf2f2c56Smiod || (! info->relocatable && !info->emitrelocations
438d2201f2fSdrahn && h->root.type != bfd_link_hash_indirect))
439d2201f2fSdrahn {
440d2201f2fSdrahn /* Make sure we don't get confused on invalid input. */
441d2201f2fSdrahn (*_bfd_error_handler)
442d2201f2fSdrahn (_("%s: encountered datalabel symbol in input"),
443d2201f2fSdrahn bfd_get_filename (abfd));
444d2201f2fSdrahn bfd_set_error (bfd_error_bad_value);
445d2201f2fSdrahn return FALSE;
446d2201f2fSdrahn }
447d2201f2fSdrahn
448d2201f2fSdrahn /* Now find the hash-table slot for this entry and fill it in. */
449d2201f2fSdrahn while (*sym_hash != NULL)
450d2201f2fSdrahn sym_hash++;
451d2201f2fSdrahn *sym_hash = h;
452d2201f2fSdrahn
453d2201f2fSdrahn /* Signal to caller to skip this symbol - we've handled it. */
454d2201f2fSdrahn *namep = NULL;
455d2201f2fSdrahn }
456d2201f2fSdrahn
457d2201f2fSdrahn return TRUE;
458d2201f2fSdrahn }
459d2201f2fSdrahn
460d2201f2fSdrahn /* This hook function is called before the linker writes out a global
461d2201f2fSdrahn symbol. For relocatable links, DataLabel symbols will be present in
462d2201f2fSdrahn linker output. We cut off the special suffix on those symbols, so the
463d2201f2fSdrahn right name appears in the output.
464d2201f2fSdrahn
465d2201f2fSdrahn When linking and emitting relocations, there can appear global symbols
466d2201f2fSdrahn that are not referenced by relocs, but rather only implicitly through
467d2201f2fSdrahn DataLabel references, a relation that is not visible to the linker.
468d2201f2fSdrahn Since no stripping of global symbols in done when doing such linking,
469d2201f2fSdrahn we don't need to look up and make sure to emit the main symbol for each
470d2201f2fSdrahn DataLabel symbol. */
471d2201f2fSdrahn
472d2201f2fSdrahn bfd_boolean
sh64_elf_link_output_symbol_hook(struct bfd_link_info * info,const char * cname,Elf_Internal_Sym * sym,asection * input_sec ATTRIBUTE_UNUSED,struct elf_link_hash_entry * h ATTRIBUTE_UNUSED)473*cf2f2c56Smiod sh64_elf_link_output_symbol_hook (struct bfd_link_info *info,
474*cf2f2c56Smiod const char *cname,
475*cf2f2c56Smiod Elf_Internal_Sym *sym,
476*cf2f2c56Smiod asection *input_sec ATTRIBUTE_UNUSED,
477*cf2f2c56Smiod struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
478d2201f2fSdrahn {
479d2201f2fSdrahn char *name = (char *) cname;
480d2201f2fSdrahn
481*cf2f2c56Smiod if (info->relocatable || info->emitrelocations)
482d2201f2fSdrahn {
483d2201f2fSdrahn if (ELF_ST_TYPE (sym->st_info) == STT_DATALABEL)
484d2201f2fSdrahn name[strlen (name) - strlen (DATALABEL_SUFFIX)] = 0;
485d2201f2fSdrahn }
486d2201f2fSdrahn
487d2201f2fSdrahn return TRUE;
488d2201f2fSdrahn }
489d2201f2fSdrahn
490d2201f2fSdrahn /* Check a SH64-specific reloc and put the value to relocate to into
491d2201f2fSdrahn RELOCATION, ready to pass to _bfd_final_link_relocate. Return FALSE if
492d2201f2fSdrahn bad value, TRUE if ok. */
493d2201f2fSdrahn
494d2201f2fSdrahn static bfd_boolean
shmedia_prepare_reloc(struct bfd_link_info * info,bfd * abfd,asection * input_section,bfd_byte * contents,const Elf_Internal_Rela * rel,bfd_vma * relocation)495*cf2f2c56Smiod shmedia_prepare_reloc (struct bfd_link_info *info, bfd *abfd,
496*cf2f2c56Smiod asection *input_section, bfd_byte *contents,
497*cf2f2c56Smiod const Elf_Internal_Rela *rel, bfd_vma *relocation)
498d2201f2fSdrahn {
499d2201f2fSdrahn bfd_vma disp, dropped;
500d2201f2fSdrahn
501d2201f2fSdrahn switch (ELF32_R_TYPE (rel->r_info))
502d2201f2fSdrahn {
503d2201f2fSdrahn case R_SH_PT_16:
504d2201f2fSdrahn /* Check the lowest bit of the destination field. If it is 1, we
505d2201f2fSdrahn check the ISA type of the destination (i.e. the low bit of the
506d2201f2fSdrahn "relocation" value, and emit an error if the instruction does not
507d2201f2fSdrahn match). If it is 0, we change a PTA to PTB. There should never
508d2201f2fSdrahn be a PTB that should change to a PTA; that indicates a toolchain
509d2201f2fSdrahn error; a mismatch with GAS. */
510d2201f2fSdrahn {
511d2201f2fSdrahn char *msg = NULL;
512d2201f2fSdrahn bfd_vma insn = bfd_get_32 (abfd, contents + rel->r_offset);
513d2201f2fSdrahn
514d2201f2fSdrahn if (insn & (1 << 10))
515d2201f2fSdrahn {
516d2201f2fSdrahn /* Check matching insn and ISA (address of target). */
517d2201f2fSdrahn if ((insn & SHMEDIA_PTB_BIT) != 0
518d2201f2fSdrahn && ((*relocation + rel->r_addend) & 1) != 0)
519d2201f2fSdrahn msg = _("PTB mismatch: a SHmedia address (bit 0 == 1)");
520d2201f2fSdrahn else if ((insn & SHMEDIA_PTB_BIT) == 0
521d2201f2fSdrahn && ((*relocation + rel->r_addend) & 1) == 0)
522d2201f2fSdrahn msg = _("PTA mismatch: a SHcompact address (bit 0 == 0)");
523d2201f2fSdrahn
524d2201f2fSdrahn if (msg != NULL
525d2201f2fSdrahn && ! ((*info->callbacks->reloc_dangerous)
526d2201f2fSdrahn (info, msg, abfd, input_section,
527d2201f2fSdrahn rel->r_offset)))
528d2201f2fSdrahn return FALSE;
529d2201f2fSdrahn }
530d2201f2fSdrahn else
531d2201f2fSdrahn {
532d2201f2fSdrahn /* We shouldn't get here with a PTB insn and a R_SH_PT_16. It
533d2201f2fSdrahn means GAS output does not match expectations; a PTA or PTB
534d2201f2fSdrahn expressed as such (or a PT found at assembly to be PTB)
535d2201f2fSdrahn would match the test above, and PT expansion with an
536d2201f2fSdrahn unknown destination (or when relaxing) will get us here. */
537d2201f2fSdrahn if ((insn & SHMEDIA_PTB_BIT) != 0)
538d2201f2fSdrahn {
539d2201f2fSdrahn (*_bfd_error_handler)
540d2201f2fSdrahn (_("%s: GAS error: unexpected PTB insn with R_SH_PT_16"),
541d2201f2fSdrahn bfd_get_filename (input_section->owner));
542d2201f2fSdrahn return FALSE;
543d2201f2fSdrahn }
544d2201f2fSdrahn
545d2201f2fSdrahn /* Change the PTA to a PTB, if destination indicates so. */
546d2201f2fSdrahn if (((*relocation + rel->r_addend) & 1) == 0)
547d2201f2fSdrahn bfd_put_32 (abfd, insn | SHMEDIA_PTB_BIT,
548d2201f2fSdrahn contents + rel->r_offset);
549d2201f2fSdrahn }
550d2201f2fSdrahn }
551d2201f2fSdrahn
552d2201f2fSdrahn case R_SH_SHMEDIA_CODE:
553d2201f2fSdrahn case R_SH_DIR5U:
554d2201f2fSdrahn case R_SH_DIR6S:
555d2201f2fSdrahn case R_SH_DIR6U:
556d2201f2fSdrahn case R_SH_DIR10S:
557d2201f2fSdrahn case R_SH_DIR10SW:
558d2201f2fSdrahn case R_SH_DIR10SL:
559d2201f2fSdrahn case R_SH_DIR10SQ:
560d2201f2fSdrahn case R_SH_IMMS16:
561d2201f2fSdrahn case R_SH_IMMU16:
562d2201f2fSdrahn case R_SH_IMM_LOW16:
563d2201f2fSdrahn case R_SH_IMM_LOW16_PCREL:
564d2201f2fSdrahn case R_SH_IMM_MEDLOW16:
565d2201f2fSdrahn case R_SH_IMM_MEDLOW16_PCREL:
566d2201f2fSdrahn case R_SH_IMM_MEDHI16:
567d2201f2fSdrahn case R_SH_IMM_MEDHI16_PCREL:
568d2201f2fSdrahn case R_SH_IMM_HI16:
569d2201f2fSdrahn case R_SH_IMM_HI16_PCREL:
570d2201f2fSdrahn case R_SH_64:
571d2201f2fSdrahn case R_SH_64_PCREL:
572d2201f2fSdrahn break;
573d2201f2fSdrahn
574d2201f2fSdrahn default:
575d2201f2fSdrahn return FALSE;
576d2201f2fSdrahn }
577d2201f2fSdrahn
578d2201f2fSdrahn disp = (*relocation & 0xf);
579d2201f2fSdrahn dropped = 0;
580d2201f2fSdrahn switch (ELF32_R_TYPE (rel->r_info))
581d2201f2fSdrahn {
582d2201f2fSdrahn case R_SH_DIR10SW: dropped = disp & 1; break;
583d2201f2fSdrahn case R_SH_DIR10SL: dropped = disp & 3; break;
584d2201f2fSdrahn case R_SH_DIR10SQ: dropped = disp & 7; break;
585d2201f2fSdrahn }
586d2201f2fSdrahn if (dropped != 0)
587d2201f2fSdrahn {
588d2201f2fSdrahn (*_bfd_error_handler)
589d2201f2fSdrahn (_("%s: error: unaligned relocation type %d at %08x reloc %08x\n"),
590d2201f2fSdrahn bfd_get_filename (input_section->owner), ELF32_R_TYPE (rel->r_info),
591d2201f2fSdrahn (unsigned)rel->r_offset, (unsigned)relocation);
592d2201f2fSdrahn return FALSE;
593d2201f2fSdrahn }
594d2201f2fSdrahn
595d2201f2fSdrahn return TRUE;
596d2201f2fSdrahn }
597d2201f2fSdrahn
598d2201f2fSdrahn /* Helper function to locate the section holding a certain address. This
599d2201f2fSdrahn is called via bfd_map_over_sections. */
600d2201f2fSdrahn
601d2201f2fSdrahn static void
sh64_find_section_for_address(bfd * abfd ATTRIBUTE_UNUSED,asection * section,void * data)602*cf2f2c56Smiod sh64_find_section_for_address (bfd *abfd ATTRIBUTE_UNUSED,
603*cf2f2c56Smiod asection *section, void *data)
604d2201f2fSdrahn {
605d2201f2fSdrahn bfd_vma vma;
606d2201f2fSdrahn bfd_size_type size;
607d2201f2fSdrahn struct sh64_find_section_vma_data *fsec_datap
608d2201f2fSdrahn = (struct sh64_find_section_vma_data *) data;
609d2201f2fSdrahn
610d2201f2fSdrahn /* Return if already found. */
611d2201f2fSdrahn if (fsec_datap->section)
612d2201f2fSdrahn return;
613d2201f2fSdrahn
614d2201f2fSdrahn /* If this section isn't part of the addressable contents, skip it. */
615d2201f2fSdrahn if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0)
616d2201f2fSdrahn return;
617d2201f2fSdrahn
618d2201f2fSdrahn vma = bfd_get_section_vma (abfd, section);
619d2201f2fSdrahn if (fsec_datap->addr < vma)
620d2201f2fSdrahn return;
621d2201f2fSdrahn
622d2201f2fSdrahn /* FIXME: section->reloc_done isn't set properly; a generic buglet
623d2201f2fSdrahn preventing us from using bfd_get_section_size_after_reloc. */
624d2201f2fSdrahn size
625d2201f2fSdrahn = section->_cooked_size ? section->_cooked_size : section->_raw_size;
626d2201f2fSdrahn
627d2201f2fSdrahn if (fsec_datap->addr >= vma + size)
628d2201f2fSdrahn return;
629d2201f2fSdrahn
630d2201f2fSdrahn fsec_datap->section = section;
631d2201f2fSdrahn }
632d2201f2fSdrahn
633d2201f2fSdrahn /* Make sure to write out the generated entries in the .cranges section
634d2201f2fSdrahn when doing partial linking, and set bit 0 on the entry address if it
635d2201f2fSdrahn points to SHmedia code and write sorted .cranges entries when writing
636d2201f2fSdrahn executables (final linking and objcopy). */
637d2201f2fSdrahn
638d2201f2fSdrahn static void
sh64_elf_final_write_processing(bfd * abfd,bfd_boolean linker ATTRIBUTE_UNUSED)639*cf2f2c56Smiod sh64_elf_final_write_processing (bfd *abfd,
640*cf2f2c56Smiod bfd_boolean linker ATTRIBUTE_UNUSED)
641d2201f2fSdrahn {
642d2201f2fSdrahn bfd_vma ld_generated_cranges_size;
643d2201f2fSdrahn asection *cranges
644d2201f2fSdrahn = bfd_get_section_by_name (abfd, SH64_CRANGES_SECTION_NAME);
645d2201f2fSdrahn
646d2201f2fSdrahn /* If no new .cranges were added, the generic ELF linker parts will
647d2201f2fSdrahn write it all out. If not, we need to write them out when doing
648d2201f2fSdrahn partial linking. For a final link, we will sort them and write them
649d2201f2fSdrahn all out further below. */
650d2201f2fSdrahn if (linker
651d2201f2fSdrahn && cranges != NULL
652d2201f2fSdrahn && elf_elfheader (abfd)->e_type != ET_EXEC
653d2201f2fSdrahn && (ld_generated_cranges_size
654d2201f2fSdrahn = sh64_elf_section_data (cranges)->sh64_info->cranges_growth) != 0)
655d2201f2fSdrahn {
656d2201f2fSdrahn bfd_vma incoming_cranges_size
657d2201f2fSdrahn = ((cranges->_cooked_size != 0
658d2201f2fSdrahn ? cranges->_cooked_size : cranges->_raw_size)
659d2201f2fSdrahn - ld_generated_cranges_size);
660d2201f2fSdrahn
661d2201f2fSdrahn if (! bfd_set_section_contents (abfd, cranges,
662d2201f2fSdrahn cranges->contents
663d2201f2fSdrahn + incoming_cranges_size,
664d2201f2fSdrahn cranges->output_offset
665d2201f2fSdrahn + incoming_cranges_size,
666d2201f2fSdrahn ld_generated_cranges_size))
667d2201f2fSdrahn {
668d2201f2fSdrahn bfd_set_error (bfd_error_file_truncated);
669d2201f2fSdrahn (*_bfd_error_handler)
670d2201f2fSdrahn (_("%s: could not write out added .cranges entries"),
671d2201f2fSdrahn bfd_get_filename (abfd));
672d2201f2fSdrahn }
673d2201f2fSdrahn }
674d2201f2fSdrahn
675d2201f2fSdrahn /* Only set entry address bit 0 and sort .cranges when linking to an
676d2201f2fSdrahn executable; never with objcopy or strip. */
677d2201f2fSdrahn if (linker && elf_elfheader (abfd)->e_type == ET_EXEC)
678d2201f2fSdrahn {
679d2201f2fSdrahn struct sh64_find_section_vma_data fsec_data;
680d2201f2fSdrahn sh64_elf_crange dummy;
681d2201f2fSdrahn
682d2201f2fSdrahn /* For a final link, set the low bit of the entry address to
683d2201f2fSdrahn reflect whether or not it is a SHmedia address.
684d2201f2fSdrahn FIXME: Perhaps we shouldn't do this if the entry address was
685d2201f2fSdrahn supplied numerically, but we currently lack the infrastructure to
686d2201f2fSdrahn recognize that: The entry symbol, and info whether it is numeric
687d2201f2fSdrahn or a symbol name is kept private in the linker. */
688d2201f2fSdrahn fsec_data.addr = elf_elfheader (abfd)->e_entry;
689d2201f2fSdrahn fsec_data.section = NULL;
690d2201f2fSdrahn
691d2201f2fSdrahn bfd_map_over_sections (abfd, sh64_find_section_for_address,
692*cf2f2c56Smiod &fsec_data);
693d2201f2fSdrahn if (fsec_data.section
694d2201f2fSdrahn && (sh64_get_contents_type (fsec_data.section,
695d2201f2fSdrahn elf_elfheader (abfd)->e_entry,
696d2201f2fSdrahn &dummy) == CRT_SH5_ISA32))
697d2201f2fSdrahn elf_elfheader (abfd)->e_entry |= 1;
698d2201f2fSdrahn
699d2201f2fSdrahn /* If we have a .cranges section, sort the entries. */
700d2201f2fSdrahn if (cranges != NULL)
701d2201f2fSdrahn {
702d2201f2fSdrahn bfd_size_type cranges_size
703d2201f2fSdrahn = (cranges->_cooked_size != 0
704d2201f2fSdrahn ? cranges->_cooked_size : cranges->_raw_size);
705d2201f2fSdrahn
706d2201f2fSdrahn /* We know we always have these in memory at this time. */
707d2201f2fSdrahn BFD_ASSERT (cranges->contents != NULL);
708d2201f2fSdrahn
709d2201f2fSdrahn /* The .cranges may already have been sorted in the process of
710d2201f2fSdrahn finding out the ISA-type of the entry address. If not, we do
711d2201f2fSdrahn it here. */
712d2201f2fSdrahn if (elf_section_data (cranges)->this_hdr.sh_type
713d2201f2fSdrahn != SHT_SH5_CR_SORTED)
714d2201f2fSdrahn {
715d2201f2fSdrahn qsort (cranges->contents, cranges_size / SH64_CRANGE_SIZE,
716d2201f2fSdrahn SH64_CRANGE_SIZE,
717d2201f2fSdrahn bfd_big_endian (cranges->owner)
718d2201f2fSdrahn ? _bfd_sh64_crange_qsort_cmpb
719d2201f2fSdrahn : _bfd_sh64_crange_qsort_cmpl);
720d2201f2fSdrahn elf_section_data (cranges)->this_hdr.sh_type
721d2201f2fSdrahn = SHT_SH5_CR_SORTED;
722d2201f2fSdrahn }
723d2201f2fSdrahn
724d2201f2fSdrahn /* We need to write it out in whole as sorted. */
725d2201f2fSdrahn if (! bfd_set_section_contents (abfd, cranges,
726d2201f2fSdrahn cranges->contents,
727d2201f2fSdrahn cranges->output_offset,
728d2201f2fSdrahn cranges_size))
729d2201f2fSdrahn {
730d2201f2fSdrahn bfd_set_error (bfd_error_file_truncated);
731d2201f2fSdrahn (*_bfd_error_handler)
732d2201f2fSdrahn (_("%s: could not write out sorted .cranges entries"),
733d2201f2fSdrahn bfd_get_filename (abfd));
734d2201f2fSdrahn }
735d2201f2fSdrahn }
736d2201f2fSdrahn }
737d2201f2fSdrahn }
738d2201f2fSdrahn
739*cf2f2c56Smiod /* Merge non visibility st_other attribute when the symbol comes from
740*cf2f2c56Smiod a dynamic object. */
741*cf2f2c56Smiod static void
sh64_elf_merge_symbol_attribute(struct elf_link_hash_entry * h,const Elf_Internal_Sym * isym,bfd_boolean definition,bfd_boolean dynamic)742*cf2f2c56Smiod sh64_elf_merge_symbol_attribute (struct elf_link_hash_entry *h,
743*cf2f2c56Smiod const Elf_Internal_Sym *isym,
744*cf2f2c56Smiod bfd_boolean definition,
745*cf2f2c56Smiod bfd_boolean dynamic)
746*cf2f2c56Smiod {
747*cf2f2c56Smiod if (isym->st_other != 0 && dynamic)
748*cf2f2c56Smiod {
749*cf2f2c56Smiod unsigned char other;
750*cf2f2c56Smiod
751*cf2f2c56Smiod /* Take the balance of OTHER from the definition. */
752*cf2f2c56Smiod other = (definition ? isym->st_other : h->other);
753*cf2f2c56Smiod other &= ~ ELF_ST_VISIBILITY (-1);
754*cf2f2c56Smiod h->other = other | ELF_ST_VISIBILITY (h->other);
755*cf2f2c56Smiod }
756*cf2f2c56Smiod
757*cf2f2c56Smiod return;
758*cf2f2c56Smiod }
759*cf2f2c56Smiod
760*cf2f2c56Smiod static struct bfd_elf_special_section const sh64_elf_special_sections[]=
761*cf2f2c56Smiod {
762*cf2f2c56Smiod { ".cranges", 8, 0, SHT_PROGBITS, 0 },
763*cf2f2c56Smiod { NULL, 0, 0, 0, 0 }
764*cf2f2c56Smiod };
765*cf2f2c56Smiod
766d2201f2fSdrahn #undef TARGET_BIG_SYM
767d2201f2fSdrahn #define TARGET_BIG_SYM bfd_elf32_sh64_vec
768d2201f2fSdrahn #undef TARGET_BIG_NAME
769d2201f2fSdrahn #define TARGET_BIG_NAME "elf32-sh64"
770d2201f2fSdrahn #undef TARGET_LITTLE_SYM
771d2201f2fSdrahn #define TARGET_LITTLE_SYM bfd_elf32_sh64l_vec
772d2201f2fSdrahn #undef TARGET_LITTLE_NAME
773d2201f2fSdrahn #define TARGET_LITTLE_NAME "elf32-sh64l"
774d2201f2fSdrahn
775d2201f2fSdrahn #include "elf32-target.h"
776d2201f2fSdrahn
777d2201f2fSdrahn /* NetBSD support. */
778d2201f2fSdrahn #undef TARGET_BIG_SYM
779d2201f2fSdrahn #define TARGET_BIG_SYM bfd_elf32_sh64nbsd_vec
780d2201f2fSdrahn #undef TARGET_BIG_NAME
781d2201f2fSdrahn #define TARGET_BIG_NAME "elf32-sh64-nbsd"
782d2201f2fSdrahn #undef TARGET_LITTLE_SYM
783d2201f2fSdrahn #define TARGET_LITTLE_SYM bfd_elf32_sh64lnbsd_vec
784d2201f2fSdrahn #undef TARGET_LITTLE_NAME
785d2201f2fSdrahn #define TARGET_LITTLE_NAME "elf32-sh64l-nbsd"
786d2201f2fSdrahn #undef ELF_MAXPAGESIZE
787d2201f2fSdrahn #define ELF_MAXPAGESIZE 0x10000
788d2201f2fSdrahn #undef elf_symbol_leading_char
789d2201f2fSdrahn #define elf_symbol_leading_char 0
790d2201f2fSdrahn #undef elf32_bed
791d2201f2fSdrahn #define elf32_bed elf32_sh64_nbsd_bed
792d2201f2fSdrahn
793d2201f2fSdrahn #include "elf32-target.h"
794d2201f2fSdrahn
795d2201f2fSdrahn /* Linux support. */
796d2201f2fSdrahn #undef TARGET_BIG_SYM
797d2201f2fSdrahn #define TARGET_BIG_SYM bfd_elf32_sh64blin_vec
798d2201f2fSdrahn #undef TARGET_BIG_NAME
799d2201f2fSdrahn #define TARGET_BIG_NAME "elf32-sh64big-linux"
800d2201f2fSdrahn #undef TARGET_LITTLE_SYM
801d2201f2fSdrahn #define TARGET_LITTLE_SYM bfd_elf32_sh64lin_vec
802d2201f2fSdrahn #undef TARGET_LITTLE_NAME
803d2201f2fSdrahn #define TARGET_LITTLE_NAME "elf32-sh64-linux"
804d2201f2fSdrahn #undef elf32_bed
805d2201f2fSdrahn #define elf32_bed elf32_sh64_lin_bed
806d2201f2fSdrahn
807d2201f2fSdrahn #include "elf32-target.h"
808d2201f2fSdrahn
809