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