1 |
/* Hitachi SH64-specific support for 32-bit ELF |
/* SuperH SH64-specific support for 32-bit ELF |
2 |
Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. |
Copyright 2000, 2001, 2002, 2003, 2004, 2005 |
3 |
|
Free Software Foundation, Inc. |
4 |
|
|
5 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
6 |
|
|
24 |
#include "sysdep.h" |
#include "sysdep.h" |
25 |
#include "elf-bfd.h" |
#include "elf-bfd.h" |
26 |
#include "../opcodes/sh64-opc.h" |
#include "../opcodes/sh64-opc.h" |
27 |
|
#include "elf32-sh64.h" |
28 |
|
|
29 |
/* Add a suffix for datalabel indirection symbols. It must not match any |
/* Add a suffix for datalabel indirection symbols. It must not match any |
30 |
other symbols; user symbols with or without version or other |
other symbols; user symbols with or without version or other |
39 |
bfd_vma addr; |
bfd_vma addr; |
40 |
}; |
}; |
41 |
|
|
42 |
static boolean sh64_elf_copy_private_data PARAMS ((bfd *, bfd *)); |
static bfd_boolean sh64_elf_new_section_hook |
43 |
static boolean sh64_elf_merge_private_data PARAMS ((bfd *, bfd *)); |
(bfd *, asection *); |
44 |
static boolean sh64_elf_fake_sections PARAMS ((bfd *, Elf_Internal_Shdr *, |
static bfd_boolean sh64_elf_copy_private_data |
45 |
asection *)); |
(bfd *, bfd *); |
46 |
static boolean sh64_elf_set_private_flags PARAMS ((bfd *, flagword)); |
static bfd_boolean sh64_elf_merge_private_data |
47 |
static boolean sh64_elf_set_mach_from_flags PARAMS ((bfd *)); |
(bfd *, bfd *); |
48 |
static boolean shmedia_prepare_reloc |
static bfd_boolean sh64_elf_fake_sections |
49 |
PARAMS ((struct bfd_link_info *, bfd *, asection *, |
(bfd *, Elf_Internal_Shdr *, asection *); |
50 |
bfd_byte *, const Elf_Internal_Rela *, bfd_vma *)); |
static bfd_boolean sh64_elf_set_private_flags |
51 |
static int sh64_elf_get_symbol_type PARAMS ((Elf_Internal_Sym *, int)); |
(bfd *, flagword); |
52 |
static boolean sh64_elf_add_symbol_hook |
static bfd_boolean sh64_elf_set_mach_from_flags |
53 |
PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *, |
(bfd *); |
54 |
const char **, flagword *, asection **, bfd_vma *)); |
static bfd_boolean shmedia_prepare_reloc |
55 |
static boolean sh64_elf_link_output_symbol_hook |
(struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
56 |
PARAMS ((bfd *, struct bfd_link_info *, const char *, Elf_Internal_Sym *, |
const Elf_Internal_Rela *, bfd_vma *); |
57 |
asection *)); |
static int sh64_elf_get_symbol_type |
58 |
static boolean sh64_backend_section_from_shdr |
(Elf_Internal_Sym *, int); |
59 |
PARAMS ((bfd *, Elf_Internal_Shdr *, const char *)); |
static bfd_boolean sh64_elf_add_symbol_hook |
60 |
static void sh64_elf_final_write_processing PARAMS ((bfd *, boolean)); |
(bfd *, struct bfd_link_info *, Elf_Internal_Sym *, const char **, |
61 |
static boolean sh64_bfd_elf_copy_private_section_data |
flagword *, asection **, bfd_vma *); |
62 |
PARAMS ((bfd *, asection *, bfd *, asection *)); |
static bfd_boolean sh64_elf_link_output_symbol_hook |
63 |
static void sh64_find_section_for_address PARAMS ((bfd *, asection *, PTR)); |
(struct bfd_link_info *, const char *, Elf_Internal_Sym *, asection *, |
64 |
|
struct elf_link_hash_entry *); |
65 |
|
static bfd_boolean sh64_backend_section_from_shdr |
66 |
|
(bfd *, Elf_Internal_Shdr *, const char *); |
67 |
|
static void sh64_elf_final_write_processing |
68 |
|
(bfd *, bfd_boolean); |
69 |
|
static bfd_boolean sh64_bfd_elf_copy_private_section_data |
70 |
|
(bfd *, asection *, bfd *, asection *); |
71 |
|
static void sh64_find_section_for_address |
72 |
|
(bfd *, asection *, void *); |
73 |
|
|
74 |
/* Let elf32-sh.c handle the "bfd_" definitions, so we only have to |
/* Let elf32-sh.c handle the "bfd_" definitions, so we only have to |
75 |
intrude with an #ifndef around the function definition. */ |
intrude with an #ifndef around the function definition. */ |
86 |
#define elf_backend_add_symbol_hook sh64_elf_add_symbol_hook |
#define elf_backend_add_symbol_hook sh64_elf_add_symbol_hook |
87 |
#define elf_backend_link_output_symbol_hook \ |
#define elf_backend_link_output_symbol_hook \ |
88 |
sh64_elf_link_output_symbol_hook |
sh64_elf_link_output_symbol_hook |
89 |
|
#define elf_backend_merge_symbol_attribute sh64_elf_merge_symbol_attribute |
90 |
#define elf_backend_final_write_processing sh64_elf_final_write_processing |
#define elf_backend_final_write_processing sh64_elf_final_write_processing |
91 |
#define elf_backend_section_from_shdr sh64_backend_section_from_shdr |
#define elf_backend_section_from_shdr sh64_backend_section_from_shdr |
92 |
|
#define elf_backend_special_sections sh64_elf_special_sections |
93 |
|
#define elf_backend_section_flags sh64_elf_section_flags |
94 |
|
|
95 |
|
#define bfd_elf32_new_section_hook sh64_elf_new_section_hook |
96 |
|
|
97 |
/* For objcopy, we need to set up sh64_elf_section_data (asection *) from |
/* For objcopy, we need to set up sh64_elf_section_data (asection *) from |
98 |
incoming section flags. This is otherwise done in sh64elf.em when |
incoming section flags. This is otherwise done in sh64elf.em when |
101 |
sh64_bfd_elf_copy_private_section_data |
sh64_bfd_elf_copy_private_section_data |
102 |
|
|
103 |
/* This COFF-only function (only compiled with COFF support, making |
/* This COFF-only function (only compiled with COFF support, making |
104 |
ELF-only chains problematic) returns true early for SH4, so let's just |
ELF-only chains problematic) returns TRUE early for SH4, so let's just |
105 |
define it true here. */ |
define it TRUE here. */ |
106 |
#define _bfd_sh_align_load_span(a,b,c,d,e,f,g,h,i,j) true |
#define _bfd_sh_align_load_span(a,b,c,d,e,f,g,h,i,j) TRUE |
|
|
|
|
#ifndef ELF_ARCH |
|
|
#define TARGET_BIG_SYM bfd_elf32_sh64_vec |
|
|
#define TARGET_BIG_NAME "elf32-sh64" |
|
|
#define TARGET_LITTLE_SYM bfd_elf32_sh64l_vec |
|
|
#define TARGET_LITTLE_NAME "elf32-sh64l" |
|
|
#define ELF_ARCH bfd_arch_sh |
|
|
#define ELF_MACHINE_CODE EM_SH |
|
|
#define ELF_MAXPAGESIZE 128 |
|
|
|
|
|
#define elf_symbol_leading_char '_' |
|
|
#endif /* ELF_ARCH */ |
|
107 |
|
|
108 |
#define GOT_BIAS (-((long)-32768)) |
#define GOT_BIAS (-((long)-32768)) |
109 |
#define INCLUDE_SHMEDIA |
#define INCLUDE_SHMEDIA |
110 |
|
#define SH_TARGET_ALREADY_DEFINED |
111 |
#include "elf32-sh.c" |
#include "elf32-sh.c" |
112 |
|
|
113 |
|
/* Tack some extra info on struct bfd_elf_section_data. */ |
114 |
|
|
115 |
|
static bfd_boolean |
116 |
|
sh64_elf_new_section_hook (bfd *abfd, asection *sec) |
117 |
|
{ |
118 |
|
struct _sh64_elf_section_data *sdata; |
119 |
|
bfd_size_type amt = sizeof (*sdata); |
120 |
|
|
121 |
|
sdata = (struct _sh64_elf_section_data *) bfd_zalloc (abfd, amt); |
122 |
|
if (sdata == NULL) |
123 |
|
return FALSE; |
124 |
|
sec->used_by_bfd = sdata; |
125 |
|
|
126 |
|
return _bfd_elf_new_section_hook (abfd, sec); |
127 |
|
} |
128 |
|
|
129 |
/* Set the SHF_SH5_ISA32 flag for ISA SHmedia code sections, and pass |
/* Set the SHF_SH5_ISA32 flag for ISA SHmedia code sections, and pass |
130 |
through SHT_SH5_CR_SORTED on a sorted .cranges section. */ |
through SHT_SH5_CR_SORTED on a sorted .cranges section. */ |
131 |
|
|
132 |
boolean |
bfd_boolean |
133 |
sh64_elf_fake_sections (output_bfd, elf_section_hdr, asect) |
sh64_elf_fake_sections (bfd *output_bfd ATTRIBUTE_UNUSED, |
134 |
bfd *output_bfd ATTRIBUTE_UNUSED; |
Elf_Internal_Shdr *elf_section_hdr, |
135 |
Elf_Internal_Shdr *elf_section_hdr; |
asection *asect) |
|
asection *asect; |
|
136 |
{ |
{ |
137 |
if (sh64_elf_section_data (asect) != NULL) |
if (sh64_elf_section_data (asect)->sh64_info != NULL) |
138 |
elf_section_hdr->sh_flags |
elf_section_hdr->sh_flags |
139 |
|= sh64_elf_section_data (asect)->contents_flags; |
|= sh64_elf_section_data (asect)->sh64_info->contents_flags; |
140 |
|
|
141 |
/* If this section has the SEC_SORT_ENTRIES flag set, it is a sorted |
/* If this section has the SEC_SORT_ENTRIES flag set, it is a sorted |
142 |
.cranges section passing through objcopy. */ |
.cranges section passing through objcopy. */ |
145 |
SH64_CRANGES_SECTION_NAME) == 0) |
SH64_CRANGES_SECTION_NAME) == 0) |
146 |
elf_section_hdr->sh_type = SHT_SH5_CR_SORTED; |
elf_section_hdr->sh_type = SHT_SH5_CR_SORTED; |
147 |
|
|
148 |
return true; |
return TRUE; |
149 |
} |
} |
150 |
|
|
151 |
static boolean |
static bfd_boolean |
152 |
sh64_elf_set_mach_from_flags (abfd) |
sh64_elf_set_mach_from_flags (bfd *abfd) |
|
bfd *abfd; |
|
153 |
{ |
{ |
154 |
flagword flags = elf_elfheader (abfd)->e_flags; |
flagword flags = elf_elfheader (abfd)->e_flags; |
|
asection *cranges; |
|
155 |
|
|
156 |
switch (flags & EF_SH_MACH_MASK) |
switch (flags & EF_SH_MACH_MASK) |
157 |
{ |
{ |
163 |
|
|
164 |
default: |
default: |
165 |
bfd_set_error (bfd_error_wrong_format); |
bfd_set_error (bfd_error_wrong_format); |
166 |
return false; |
return FALSE; |
167 |
} |
} |
168 |
|
|
169 |
/* We also need to set SEC_DEBUGGING on an incoming .cranges section. |
return TRUE; |
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 |
static bfd_boolean |
173 |
undocumented design or a bug. */ |
sh64_elf_section_flags (flagword *flags, |
174 |
cranges = bfd_get_section_by_name (abfd, SH64_CRANGES_SECTION_NAME); |
const Elf_Internal_Shdr *hdr) |
175 |
if (cranges != NULL |
{ |
176 |
&& ! bfd_set_section_flags (abfd, cranges, |
if (hdr->bfd_section == NULL) |
177 |
bfd_get_section_flags (abfd, cranges) |
return FALSE; |
178 |
| SEC_DEBUGGING)) |
|
179 |
return false; |
if (strcmp (hdr->bfd_section->name, SH64_CRANGES_SECTION_NAME) == 0) |
180 |
|
*flags |= SEC_DEBUGGING; |
181 |
return true; |
|
182 |
} |
return TRUE; |
183 |
|
} |
184 |
static boolean |
|
185 |
sh64_elf_copy_private_data (ibfd, obfd) |
static bfd_boolean |
186 |
bfd * ibfd; |
sh64_elf_copy_private_data (bfd * ibfd, bfd * obfd) |
|
bfd * obfd; |
|
187 |
{ |
{ |
188 |
if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour |
if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour |
189 |
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour) |
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour) |
190 |
return true; |
return TRUE; |
191 |
|
|
192 |
BFD_ASSERT (!elf_flags_init (obfd) |
BFD_ASSERT (!elf_flags_init (obfd) |
193 |
|| (elf_elfheader (obfd)->e_flags |
|| (elf_elfheader (obfd)->e_flags |
194 |
== elf_elfheader (ibfd)->e_flags)); |
== elf_elfheader (ibfd)->e_flags)); |
195 |
|
|
196 |
elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; |
elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; |
197 |
return true; |
return TRUE; |
198 |
} |
} |
199 |
|
|
200 |
static boolean |
static bfd_boolean |
201 |
sh64_elf_merge_private_data (ibfd, obfd) |
sh64_elf_merge_private_data (bfd *ibfd, bfd *obfd) |
|
bfd *ibfd; |
|
|
bfd *obfd; |
|
202 |
{ |
{ |
203 |
flagword old_flags, new_flags; |
flagword old_flags, new_flags; |
204 |
|
|
205 |
if (! _bfd_generic_verify_endian_match (ibfd, obfd)) |
if (! _bfd_generic_verify_endian_match (ibfd, obfd)) |
206 |
return false; |
return FALSE; |
207 |
|
|
208 |
if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour |
if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour |
209 |
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour) |
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour) |
210 |
return true; |
return TRUE; |
211 |
|
|
212 |
if (bfd_get_arch_size (ibfd) != bfd_get_arch_size (obfd)) |
if (bfd_get_arch_size (ibfd) != bfd_get_arch_size (obfd)) |
213 |
{ |
{ |
225 |
(*_bfd_error_handler) (msg, bfd_get_filename (ibfd), |
(*_bfd_error_handler) (msg, bfd_get_filename (ibfd), |
226 |
bfd_get_filename (obfd)); |
bfd_get_filename (obfd)); |
227 |
bfd_set_error (bfd_error_wrong_format); |
bfd_set_error (bfd_error_wrong_format); |
228 |
return false; |
return FALSE; |
229 |
} |
} |
230 |
|
|
231 |
old_flags = elf_elfheader (obfd)->e_flags; |
old_flags = elf_elfheader (obfd)->e_flags; |
233 |
if (! elf_flags_init (obfd)) |
if (! elf_flags_init (obfd)) |
234 |
{ |
{ |
235 |
/* This happens when ld starts out with a 'blank' output file. */ |
/* This happens when ld starts out with a 'blank' output file. */ |
236 |
elf_flags_init (obfd) = true; |
elf_flags_init (obfd) = TRUE; |
237 |
elf_elfheader (obfd)->e_flags = old_flags = new_flags; |
elf_elfheader (obfd)->e_flags = old_flags = new_flags; |
238 |
} |
} |
239 |
/* We don't allow linking in non-SH64 code. */ |
/* We don't allow linking in non-SH64 code. */ |
243 |
("%s: uses non-SH64 instructions while previous modules use SH64 instructions", |
("%s: uses non-SH64 instructions while previous modules use SH64 instructions", |
244 |
bfd_get_filename (ibfd)); |
bfd_get_filename (ibfd)); |
245 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
246 |
return false; |
return FALSE; |
247 |
} |
} |
248 |
|
|
249 |
/* I can't think of anything sane other than old_flags being EF_SH5 and |
/* I can't think of anything sane other than old_flags being EF_SH5 and |
257 |
|
|
258 |
We only recognize SHT_SH5_CR_SORTED, on the .cranges section. */ |
We only recognize SHT_SH5_CR_SORTED, on the .cranges section. */ |
259 |
|
|
260 |
boolean |
bfd_boolean |
261 |
sh64_backend_section_from_shdr (abfd, hdr, name) |
sh64_backend_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr, |
262 |
bfd *abfd; |
const char *name) |
|
Elf_Internal_Shdr *hdr; |
|
|
const char *name; |
|
263 |
{ |
{ |
264 |
flagword flags = 0; |
flagword flags = 0; |
265 |
|
|
266 |
/* We do like MIPS with a bit switch for recognized types, and returning |
/* We do like MIPS with a bit switch for recognized types, and returning |
267 |
false for a recognized section type with an unexpected name. Right |
FALSE for a recognized section type with an unexpected name. Right |
268 |
now we only have one recognized type, but that might change. */ |
now we only have one recognized type, but that might change. */ |
269 |
switch (hdr->sh_type) |
switch (hdr->sh_type) |
270 |
{ |
{ |
271 |
case SHT_SH5_CR_SORTED: |
case SHT_SH5_CR_SORTED: |
272 |
if (strcmp (name, SH64_CRANGES_SECTION_NAME) != 0) |
if (strcmp (name, SH64_CRANGES_SECTION_NAME) != 0) |
273 |
return false; |
return FALSE; |
274 |
|
|
275 |
/* We set the SEC_SORT_ENTRIES flag so it can be passed on to |
/* We set the SEC_SORT_ENTRIES flag so it can be passed on to |
276 |
sh64_elf_fake_sections, keeping SHT_SH5_CR_SORTED if this object |
sh64_elf_fake_sections, keeping SHT_SH5_CR_SORTED if this object |
281 |
break; |
break; |
282 |
|
|
283 |
default: |
default: |
284 |
return false; |
return FALSE; |
285 |
} |
} |
286 |
|
|
287 |
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) |
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) |
288 |
return false; |
return FALSE; |
289 |
|
|
290 |
if (flags |
if (flags |
291 |
&& ! bfd_set_section_flags (abfd, hdr->bfd_section, |
&& ! bfd_set_section_flags (abfd, hdr->bfd_section, |
292 |
bfd_get_section_flags (abfd, |
bfd_get_section_flags (abfd, |
293 |
hdr->bfd_section) |
hdr->bfd_section) |
294 |
| flags)) |
| flags)) |
295 |
return false; |
return FALSE; |
296 |
|
|
297 |
return true; |
return TRUE; |
298 |
} |
} |
299 |
|
|
300 |
/* In contrast to sh64_backend_section_from_shdr, this is called for all |
/* In contrast to sh64_backend_section_from_shdr, this is called for all |
302 |
assembling. We need to set up the sh64_elf_section_data (asection *) |
assembling. We need to set up the sh64_elf_section_data (asection *) |
303 |
structure for the SH64 ELF section flags to be copied correctly. */ |
structure for the SH64 ELF section flags to be copied correctly. */ |
304 |
|
|
305 |
boolean |
bfd_boolean |
306 |
sh64_bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec) |
sh64_bfd_elf_copy_private_section_data (bfd *ibfd, asection *isec, |
307 |
bfd *ibfd; |
bfd *obfd, asection *osec) |
|
asection *isec; |
|
|
bfd *obfd; |
|
|
asection *osec; |
|
308 |
{ |
{ |
309 |
struct sh64_section_data *sh64_sec_data; |
struct sh64_section_data *sh64_sec_data; |
310 |
|
|
311 |
if (ibfd->xvec->flavour != bfd_target_elf_flavour |
if (ibfd->xvec->flavour != bfd_target_elf_flavour |
312 |
|| obfd->xvec->flavour != bfd_target_elf_flavour) |
|| obfd->xvec->flavour != bfd_target_elf_flavour) |
313 |
return true; |
return TRUE; |
314 |
|
|
315 |
if (! _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)) |
if (! _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)) |
316 |
return false; |
return FALSE; |
317 |
|
|
318 |
sh64_sec_data = sh64_elf_section_data (isec); |
sh64_sec_data = sh64_elf_section_data (isec)->sh64_info; |
319 |
if (sh64_sec_data == NULL) |
if (sh64_sec_data == NULL) |
320 |
{ |
{ |
321 |
sh64_sec_data = bfd_zmalloc (sizeof (struct sh64_section_data)); |
sh64_sec_data = bfd_zmalloc (sizeof (struct sh64_section_data)); |
322 |
|
|
323 |
if (sh64_sec_data == NULL) |
if (sh64_sec_data == NULL) |
324 |
return false; |
return FALSE; |
325 |
|
|
326 |
sh64_sec_data->contents_flags |
sh64_sec_data->contents_flags |
327 |
= (elf_section_data (isec)->this_hdr.sh_flags |
= (elf_section_data (isec)->this_hdr.sh_flags |
328 |
& (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED)); |
& (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED)); |
329 |
|
|
330 |
sh64_elf_section_data (osec) = sh64_sec_data; |
sh64_elf_section_data (osec)->sh64_info = sh64_sec_data; |
331 |
} |
} |
332 |
|
|
333 |
return true; |
return TRUE; |
334 |
} |
} |
335 |
|
|
336 |
/* Function to keep SH64 specific file flags. */ |
/* Function to keep SH64 specific file flags. */ |
337 |
|
|
338 |
static boolean |
static bfd_boolean |
339 |
sh64_elf_set_private_flags (abfd, flags) |
sh64_elf_set_private_flags (bfd *abfd, flagword flags) |
|
bfd * abfd; |
|
|
flagword flags; |
|
340 |
{ |
{ |
341 |
BFD_ASSERT (! elf_flags_init (abfd) |
BFD_ASSERT (! elf_flags_init (abfd) |
342 |
|| elf_elfheader (abfd)->e_flags == flags); |
|| elf_elfheader (abfd)->e_flags == flags); |
343 |
|
|
344 |
elf_elfheader (abfd)->e_flags = flags; |
elf_elfheader (abfd)->e_flags = flags; |
345 |
elf_flags_init (abfd) = true; |
elf_flags_init (abfd) = TRUE; |
346 |
return sh64_elf_set_mach_from_flags (abfd); |
return sh64_elf_set_mach_from_flags (abfd); |
347 |
} |
} |
348 |
|
|
349 |
/* Called when writing out an object file to decide the type of a symbol. */ |
/* Called when writing out an object file to decide the type of a symbol. */ |
350 |
|
|
351 |
static int |
static int |
352 |
sh64_elf_get_symbol_type (elf_sym, type) |
sh64_elf_get_symbol_type (Elf_Internal_Sym *elf_sym, int type) |
|
Elf_Internal_Sym * elf_sym; |
|
|
int type; |
|
353 |
{ |
{ |
354 |
if (ELF_ST_TYPE (elf_sym->st_info) == STT_DATALABEL) |
if (ELF_ST_TYPE (elf_sym->st_info) == STT_DATALABEL) |
355 |
return STT_DATALABEL; |
return STT_DATALABEL; |
375 |
or the hash entry, alternatively adding the index to Elf_Internal_Sym |
or the hash entry, alternatively adding the index to Elf_Internal_Sym |
376 |
(not so good). */ |
(not so good). */ |
377 |
|
|
378 |
static boolean |
static bfd_boolean |
379 |
sh64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) |
sh64_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, |
380 |
bfd *abfd; |
Elf_Internal_Sym *sym, const char **namep, |
381 |
struct bfd_link_info *info; |
flagword *flagsp ATTRIBUTE_UNUSED, |
382 |
const Elf_Internal_Sym *sym; |
asection **secp, bfd_vma *valp) |
|
const char **namep; |
|
|
flagword *flagsp ATTRIBUTE_UNUSED; |
|
|
asection **secp; |
|
|
bfd_vma *valp; |
|
383 |
{ |
{ |
384 |
/* We want to do this for relocatable as well as final linking. */ |
/* We want to do this for relocatable as well as final linking. */ |
385 |
if (ELF_ST_TYPE (sym->st_info) == STT_DATALABEL |
if (ELF_ST_TYPE (sym->st_info) == STT_DATALABEL |
386 |
&& info->hash->creator->flavour == bfd_target_elf_flavour) |
&& is_elf_hash_table (info->hash)) |
387 |
{ |
{ |
388 |
struct elf_link_hash_entry *h; |
struct elf_link_hash_entry *h; |
389 |
|
|
390 |
/* For relocateable links, we register the DataLabel sym in its own |
/* For relocatable links, we register the DataLabel sym in its own |
391 |
right, and tweak the name when it's output. Otherwise, we make |
right, and tweak the name when it's output. Otherwise, we make |
392 |
an indirect symbol of it. */ |
an indirect symbol of it. */ |
393 |
flagword flags |
flagword flags |
394 |
= info->relocateable || info->emitrelocations |
= info->relocatable || info->emitrelocations |
395 |
? BSF_GLOBAL : BSF_GLOBAL | BSF_INDIRECT; |
? BSF_GLOBAL : BSF_GLOBAL | BSF_INDIRECT; |
396 |
|
|
397 |
char *dl_name |
char *dl_name |
402 |
|
|
403 |
/* Allocation may fail. */ |
/* Allocation may fail. */ |
404 |
if (dl_name == NULL) |
if (dl_name == NULL) |
405 |
return false; |
return FALSE; |
406 |
|
|
407 |
strcpy (dl_name, *namep); |
strcpy (dl_name, *namep); |
408 |
strcat (dl_name, DATALABEL_SUFFIX); |
strcat (dl_name, DATALABEL_SUFFIX); |
409 |
|
|
410 |
h = (struct elf_link_hash_entry *) |
h = (struct elf_link_hash_entry *) |
411 |
bfd_link_hash_lookup (info->hash, dl_name, false, false, false); |
bfd_link_hash_lookup (info->hash, dl_name, FALSE, FALSE, FALSE); |
412 |
|
|
413 |
if (h == NULL) |
if (h == NULL) |
414 |
{ |
{ |
415 |
/* No previous datalabel symbol. Make one. */ |
/* No previous datalabel symbol. Make one. */ |
416 |
|
struct bfd_link_hash_entry *bh = NULL; |
417 |
|
const struct elf_backend_data *bed = get_elf_backend_data (abfd); |
418 |
|
|
419 |
if (! _bfd_generic_link_add_one_symbol (info, abfd, dl_name, |
if (! _bfd_generic_link_add_one_symbol (info, abfd, dl_name, |
420 |
flags, *secp, *valp, |
flags, *secp, *valp, |
421 |
*namep, false, |
*namep, FALSE, |
422 |
get_elf_backend_data (abfd)->collect, |
bed->collect, &bh)) |
|
(struct bfd_link_hash_entry **) &h)) |
|
423 |
{ |
{ |
424 |
free (dl_name); |
free (dl_name); |
425 |
return false; |
return FALSE; |
426 |
} |
} |
427 |
|
|
428 |
h->elf_link_hash_flags &=~ ELF_LINK_NON_ELF; |
h = (struct elf_link_hash_entry *) bh; |
429 |
|
h->non_elf = 0; |
430 |
h->type = STT_DATALABEL; |
h->type = STT_DATALABEL; |
431 |
} |
} |
432 |
else |
else |
435 |
free (dl_name); |
free (dl_name); |
436 |
|
|
437 |
if (h->type != STT_DATALABEL |
if (h->type != STT_DATALABEL |
438 |
|| ((info->relocateable || info->emitrelocations) |
|| ((info->relocatable || info->emitrelocations) |
439 |
&& h->root.type != bfd_link_hash_undefined) |
&& h->root.type != bfd_link_hash_undefined) |
440 |
|| (! info->relocateable && !info->emitrelocations |
|| (! info->relocatable && !info->emitrelocations |
441 |
&& h->root.type != bfd_link_hash_indirect)) |
&& h->root.type != bfd_link_hash_indirect)) |
442 |
{ |
{ |
443 |
/* Make sure we don't get confused on invalid input. */ |
/* Make sure we don't get confused on invalid input. */ |
445 |
(_("%s: encountered datalabel symbol in input"), |
(_("%s: encountered datalabel symbol in input"), |
446 |
bfd_get_filename (abfd)); |
bfd_get_filename (abfd)); |
447 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
448 |
return false; |
return FALSE; |
449 |
} |
} |
450 |
|
|
451 |
/* Now find the hash-table slot for this entry and fill it in. */ |
/* Now find the hash-table slot for this entry and fill it in. */ |
457 |
*namep = NULL; |
*namep = NULL; |
458 |
} |
} |
459 |
|
|
460 |
return true; |
return TRUE; |
461 |
} |
} |
462 |
|
|
463 |
/* This hook function is called before the linker writes out a global |
/* This hook function is called before the linker writes out a global |
472 |
we don't need to look up and make sure to emit the main symbol for each |
we don't need to look up and make sure to emit the main symbol for each |
473 |
DataLabel symbol. */ |
DataLabel symbol. */ |
474 |
|
|
475 |
boolean |
bfd_boolean |
476 |
sh64_elf_link_output_symbol_hook (abfd, info, cname, sym, input_sec) |
sh64_elf_link_output_symbol_hook (struct bfd_link_info *info, |
477 |
bfd *abfd ATTRIBUTE_UNUSED; |
const char *cname, |
478 |
struct bfd_link_info *info; |
Elf_Internal_Sym *sym, |
479 |
const char *cname; |
asection *input_sec ATTRIBUTE_UNUSED, |
480 |
Elf_Internal_Sym *sym; |
struct elf_link_hash_entry *h ATTRIBUTE_UNUSED) |
|
asection *input_sec ATTRIBUTE_UNUSED; |
|
481 |
{ |
{ |
482 |
char *name = (char *) cname; |
char *name = (char *) cname; |
483 |
|
|
484 |
if (info->relocateable || info->emitrelocations) |
if (info->relocatable || info->emitrelocations) |
485 |
{ |
{ |
486 |
if (ELF_ST_TYPE (sym->st_info) == STT_DATALABEL) |
if (ELF_ST_TYPE (sym->st_info) == STT_DATALABEL) |
487 |
name[strlen (name) - strlen (DATALABEL_SUFFIX)] = 0; |
name[strlen (name) - strlen (DATALABEL_SUFFIX)] = 0; |
488 |
} |
} |
489 |
|
|
490 |
return true; |
return TRUE; |
491 |
} |
} |
492 |
|
|
493 |
/* Check a SH64-specific reloc and put the value to relocate to into |
/* Check a SH64-specific reloc and put the value to relocate to into |
494 |
RELOCATION, ready to pass to _bfd_final_link_relocate. Return FALSE if |
RELOCATION, ready to pass to _bfd_final_link_relocate. Return FALSE if |
495 |
bad value, TRUE if ok. */ |
bad value, TRUE if ok. */ |
496 |
|
|
497 |
static boolean |
static bfd_boolean |
498 |
shmedia_prepare_reloc (info, abfd, input_section, |
shmedia_prepare_reloc (struct bfd_link_info *info, bfd *abfd, |
499 |
contents, rel, relocation) |
asection *input_section, bfd_byte *contents, |
500 |
struct bfd_link_info *info; |
const Elf_Internal_Rela *rel, bfd_vma *relocation) |
|
bfd *abfd; |
|
|
asection *input_section; |
|
|
bfd_byte *contents; |
|
|
const Elf_Internal_Rela *rel; |
|
|
bfd_vma *relocation; |
|
501 |
{ |
{ |
502 |
bfd_vma disp, dropped; |
bfd_vma disp, dropped; |
503 |
|
|
528 |
&& ! ((*info->callbacks->reloc_dangerous) |
&& ! ((*info->callbacks->reloc_dangerous) |
529 |
(info, msg, abfd, input_section, |
(info, msg, abfd, input_section, |
530 |
rel->r_offset))) |
rel->r_offset))) |
531 |
return false; |
return FALSE; |
532 |
} |
} |
533 |
else |
else |
534 |
{ |
{ |
542 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
543 |
(_("%s: GAS error: unexpected PTB insn with R_SH_PT_16"), |
(_("%s: GAS error: unexpected PTB insn with R_SH_PT_16"), |
544 |
bfd_get_filename (input_section->owner)); |
bfd_get_filename (input_section->owner)); |
545 |
return false; |
return FALSE; |
546 |
} |
} |
547 |
|
|
548 |
/* Change the PTA to a PTB, if destination indicates so. */ |
/* Change the PTA to a PTB, if destination indicates so. */ |
575 |
break; |
break; |
576 |
|
|
577 |
default: |
default: |
578 |
return false; |
return FALSE; |
579 |
} |
} |
580 |
|
|
581 |
disp = (*relocation & 0xf); |
disp = (*relocation & 0xf); |
589 |
if (dropped != 0) |
if (dropped != 0) |
590 |
{ |
{ |
591 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
592 |
(_("%s: error: unaligned relocation type %d at %08x reloc %08x\n"), |
(_("%B: error: unaligned relocation type %d at %08x reloc %p\n"), |
593 |
bfd_get_filename (input_section->owner), ELF32_R_TYPE (rel->r_info), |
input_section->owner, ELF32_R_TYPE (rel->r_info), |
594 |
(unsigned)rel->r_offset, (unsigned)relocation); |
(unsigned) rel->r_offset, relocation); |
595 |
return false; |
return FALSE; |
596 |
} |
} |
597 |
|
|
598 |
return true; |
return TRUE; |
599 |
} |
} |
600 |
|
|
601 |
/* Helper function to locate the section holding a certain address. This |
/* Helper function to locate the section holding a certain address. This |
602 |
is called via bfd_map_over_sections. */ |
is called via bfd_map_over_sections. */ |
603 |
|
|
604 |
static void |
static void |
605 |
sh64_find_section_for_address (abfd, section, data) |
sh64_find_section_for_address (bfd *abfd ATTRIBUTE_UNUSED, |
606 |
bfd *abfd ATTRIBUTE_UNUSED; |
asection *section, void *data) |
|
asection *section; |
|
|
PTR data; |
|
607 |
{ |
{ |
608 |
bfd_vma vma; |
bfd_vma vma; |
609 |
bfd_size_type size; |
bfd_size_type size; |
610 |
|
|
611 |
struct sh64_find_section_vma_data *fsec_datap |
struct sh64_find_section_vma_data *fsec_datap |
612 |
= (struct sh64_find_section_vma_data *) data; |
= (struct sh64_find_section_vma_data *) data; |
613 |
|
|
623 |
if (fsec_datap->addr < vma) |
if (fsec_datap->addr < vma) |
624 |
return; |
return; |
625 |
|
|
626 |
/* FIXME: section->reloc_done isn't set properly; a generic buglet |
size = section->size; |
|
preventing us from using bfd_get_section_size_after_reloc. */ |
|
|
size |
|
|
= section->_cooked_size ? section->_cooked_size : section->_raw_size; |
|
|
|
|
627 |
if (fsec_datap->addr >= vma + size) |
if (fsec_datap->addr >= vma + size) |
628 |
return; |
return; |
629 |
|
|
636 |
executables (final linking and objcopy). */ |
executables (final linking and objcopy). */ |
637 |
|
|
638 |
static void |
static void |
639 |
sh64_elf_final_write_processing (abfd, linker) |
sh64_elf_final_write_processing (bfd *abfd, |
640 |
bfd * abfd; |
bfd_boolean linker ATTRIBUTE_UNUSED) |
|
boolean linker ATTRIBUTE_UNUSED; |
|
641 |
{ |
{ |
642 |
bfd_vma ld_generated_cranges_size; |
bfd_vma ld_generated_cranges_size; |
643 |
asection *cranges |
asection *cranges |
651 |
&& cranges != NULL |
&& cranges != NULL |
652 |
&& elf_elfheader (abfd)->e_type != ET_EXEC |
&& elf_elfheader (abfd)->e_type != ET_EXEC |
653 |
&& (ld_generated_cranges_size |
&& (ld_generated_cranges_size |
654 |
= sh64_elf_section_data (cranges)->cranges_growth) != 0) |
= sh64_elf_section_data (cranges)->sh64_info->cranges_growth) != 0) |
655 |
{ |
{ |
656 |
bfd_vma incoming_cranges_size |
bfd_vma incoming_cranges_size |
657 |
= ((cranges->_cooked_size != 0 |
= cranges->size - ld_generated_cranges_size; |
|
? cranges->_cooked_size : cranges->_raw_size) |
|
|
- ld_generated_cranges_size); |
|
658 |
|
|
659 |
if (! bfd_set_section_contents (abfd, cranges, |
if (! bfd_set_section_contents (abfd, cranges, |
660 |
cranges->contents |
cranges->contents |
687 |
fsec_data.section = NULL; |
fsec_data.section = NULL; |
688 |
|
|
689 |
bfd_map_over_sections (abfd, sh64_find_section_for_address, |
bfd_map_over_sections (abfd, sh64_find_section_for_address, |
690 |
(PTR) &fsec_data); |
&fsec_data); |
691 |
if (fsec_data.section |
if (fsec_data.section |
692 |
&& (sh64_get_contents_type (fsec_data.section, |
&& (sh64_get_contents_type (fsec_data.section, |
693 |
elf_elfheader (abfd)->e_entry, |
elf_elfheader (abfd)->e_entry, |
697 |
/* If we have a .cranges section, sort the entries. */ |
/* If we have a .cranges section, sort the entries. */ |
698 |
if (cranges != NULL) |
if (cranges != NULL) |
699 |
{ |
{ |
700 |
bfd_size_type cranges_size |
bfd_size_type cranges_size = cranges->size; |
|
= (cranges->_cooked_size != 0 |
|
|
? cranges->_cooked_size : cranges->_raw_size); |
|
701 |
|
|
702 |
/* We know we always have these in memory at this time. */ |
/* We know we always have these in memory at this time. */ |
703 |
BFD_ASSERT (cranges->contents != NULL); |
BFD_ASSERT (cranges->contents != NULL); |
731 |
} |
} |
732 |
} |
} |
733 |
} |
} |
734 |
|
|
735 |
|
/* Merge non visibility st_other attribute when the symbol comes from |
736 |
|
a dynamic object. */ |
737 |
|
static void |
738 |
|
sh64_elf_merge_symbol_attribute (struct elf_link_hash_entry *h, |
739 |
|
const Elf_Internal_Sym *isym, |
740 |
|
bfd_boolean definition, |
741 |
|
bfd_boolean dynamic) |
742 |
|
{ |
743 |
|
if (isym->st_other != 0 && dynamic) |
744 |
|
{ |
745 |
|
unsigned char other; |
746 |
|
|
747 |
|
/* Take the balance of OTHER from the definition. */ |
748 |
|
other = (definition ? isym->st_other : h->other); |
749 |
|
other &= ~ ELF_ST_VISIBILITY (-1); |
750 |
|
h->other = other | ELF_ST_VISIBILITY (h->other); |
751 |
|
} |
752 |
|
|
753 |
|
return; |
754 |
|
} |
755 |
|
|
756 |
|
static struct bfd_elf_special_section const sh64_elf_special_sections[]= |
757 |
|
{ |
758 |
|
{ ".cranges", 8, 0, SHT_PROGBITS, 0 }, |
759 |
|
{ NULL, 0, 0, 0, 0 } |
760 |
|
}; |
761 |
|
|
762 |
|
#undef TARGET_BIG_SYM |
763 |
|
#define TARGET_BIG_SYM bfd_elf32_sh64_vec |
764 |
|
#undef TARGET_BIG_NAME |
765 |
|
#define TARGET_BIG_NAME "elf32-sh64" |
766 |
|
#undef TARGET_LITTLE_SYM |
767 |
|
#define TARGET_LITTLE_SYM bfd_elf32_sh64l_vec |
768 |
|
#undef TARGET_LITTLE_NAME |
769 |
|
#define TARGET_LITTLE_NAME "elf32-sh64l" |
770 |
|
|
771 |
|
#include "elf32-target.h" |
772 |
|
|
773 |
|
/* NetBSD support. */ |
774 |
|
#undef TARGET_BIG_SYM |
775 |
|
#define TARGET_BIG_SYM bfd_elf32_sh64nbsd_vec |
776 |
|
#undef TARGET_BIG_NAME |
777 |
|
#define TARGET_BIG_NAME "elf32-sh64-nbsd" |
778 |
|
#undef TARGET_LITTLE_SYM |
779 |
|
#define TARGET_LITTLE_SYM bfd_elf32_sh64lnbsd_vec |
780 |
|
#undef TARGET_LITTLE_NAME |
781 |
|
#define TARGET_LITTLE_NAME "elf32-sh64l-nbsd" |
782 |
|
#undef ELF_MAXPAGESIZE |
783 |
|
#define ELF_MAXPAGESIZE 0x10000 |
784 |
|
#undef elf_symbol_leading_char |
785 |
|
#define elf_symbol_leading_char 0 |
786 |
|
#undef elf32_bed |
787 |
|
#define elf32_bed elf32_sh64_nbsd_bed |
788 |
|
|
789 |
|
#include "elf32-target.h" |
790 |
|
|
791 |
|
/* Linux support. */ |
792 |
|
#undef TARGET_BIG_SYM |
793 |
|
#define TARGET_BIG_SYM bfd_elf32_sh64blin_vec |
794 |
|
#undef TARGET_BIG_NAME |
795 |
|
#define TARGET_BIG_NAME "elf32-sh64big-linux" |
796 |
|
#undef TARGET_LITTLE_SYM |
797 |
|
#define TARGET_LITTLE_SYM bfd_elf32_sh64lin_vec |
798 |
|
#undef TARGET_LITTLE_NAME |
799 |
|
#define TARGET_LITTLE_NAME "elf32-sh64-linux" |
800 |
|
#undef elf32_bed |
801 |
|
#define elf32_bed elf32_sh64_lin_bed |
802 |
|
|
803 |
|
#include "elf32-target.h" |
804 |
|
|