Enable support for the AArch64 dot-prod instruction in the Cortex A55 and A75 cpus.
[deliverable/binutils-gdb.git] / bfd / elf32-sh-symbian.c
CommitLineData
85fbca6a 1/* Renesas / SuperH specific support for Symbian 32-bit ELF files
2571583a 2 Copyright (C) 2004-2017 Free Software Foundation, Inc.
85fbca6a
NC
3 Contributed by Red Hat
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
cd123cb7 9 the Free Software Foundation; either version 3 of the License, or
85fbca6a
NC
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
cd123cb7
NC
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
21
85fbca6a
NC
22
23/* Stop elf32-sh.c from defining any target vectors. */
24#define SH_TARGET_ALREADY_DEFINED
1a320fbb 25#define sh_find_elf_flags sh_symbian_find_elf_flags
68ffbac6 26#define sh_elf_get_flags_from_mach sh_symbian_elf_get_flags_from_mach
85fbca6a
NC
27#include "elf32-sh.c"
28
29
63f2fc30
NC
30//#define SYMBIAN_DEBUG 1
31#define SYMBIAN_DEBUG 0
85fbca6a
NC
32
33#define DIRECTIVE_HEADER "#<SYMEDIT>#\n"
34#define DIRECTIVE_IMPORT "IMPORT "
35#define DIRECTIVE_EXPORT "EXPORT "
36#define DIRECTIVE_AS "AS "
37
38/* Macro to advance 's' until either it reaches 'e' or the
39 character pointed to by 's' is equal to 'c'. If 'e' is
63f2fc30 40 reached and SYMBIAN_DEBUG is enabled then the error message 'm'
85fbca6a
NC
41 is displayed. */
42#define SKIP_UNTIL(s,e,c,m) \
43 do \
44 { \
45 while (s < e && *s != c) \
46 ++ s; \
47 if (s >= e) \
48 { \
63f2fc30 49 if (SYMBIAN_DEBUG) \
85fbca6a
NC
50 fprintf (stderr, "Corrupt directive: %s\n", m); \
51 result = FALSE; \
52 } \
53 } \
54 while (0); \
55 if (!result) \
56 break;
57
58/* Like SKIP_UNTIL except there are two terminator characters
59 c1 and c2. */
60#define SKIP_UNTIL2(s,e,c1,c2,m) \
61 do \
62 { \
63 while (s < e && *s != c1 && *s != c2) \
64 ++ s; \
65 if (s >= e) \
66 { \
63f2fc30 67 if (SYMBIAN_DEBUG) \
85fbca6a
NC
68 fprintf (stderr, "Corrupt directive: %s\n", m); \
69 result = FALSE; \
70 } \
71 } \
72 while (0); \
73 if (!result) \
74 break;
75
76/* Macro to advance 's' until either it reaches 'e' or the
77 character pointed to by 's' is not equal to 'c'. If 'e'
63f2fc30 78 is reached and SYMBIAN_DEBUG is enabled then the error message
85fbca6a
NC
79 'm' is displayed. */
80#define SKIP_WHILE(s,e,c,m) \
81 do \
82 { \
83 while (s < e && *s == c) \
84 ++ s; \
85 if (s >= e) \
86 { \
63f2fc30 87 if (SYMBIAN_DEBUG) \
85fbca6a
NC
88 fprintf (stderr, "Corrupt directive: %s\n", m); \
89 result = FALSE; \
90 } \
91 } \
92 while (0); \
93 if (!result) \
94 break;
95
96
97typedef struct symbol_rename
98{
99 struct symbol_rename * next;
f075ee0c
AM
100 char * current_name;
101 char * new_name;
85fbca6a
NC
102 struct elf_link_hash_entry * current_hash;
103 unsigned long new_symndx;
104}
105symbol_rename;
106
107static symbol_rename * rename_list = NULL;
108
109/* Accumulate a list of symbols to be renamed. */
110
111static bfd_boolean
112sh_symbian_import_as (struct bfd_link_info *info, bfd * abfd,
f075ee0c 113 char * current_name, char * new_name)
85fbca6a
NC
114{
115 struct elf_link_hash_entry * new_hash;
116 symbol_rename * node;
117
63f2fc30 118 if (SYMBIAN_DEBUG)
85fbca6a
NC
119 fprintf (stderr, "IMPORT '%s' AS '%s'\n", current_name, new_name);
120
121 for (node = rename_list; node; node = node->next)
122 if (strcmp (node->current_name, current_name) == 0)
123 {
124 if (strcmp (node->new_name, new_name) == 0)
125 /* Already added to rename list. */
126 return TRUE;
127
128 bfd_set_error (bfd_error_invalid_operation);
695344c0 129 /* xgettext:c-format */
d003868e
AM
130 _bfd_error_handler (_("%B: IMPORT AS directive for %s conceals previous IMPORT AS"),
131 abfd, current_name);
68ffbac6 132 return FALSE;
85fbca6a
NC
133 }
134
135 if ((node = bfd_malloc (sizeof * node)) == NULL)
136 {
63f2fc30 137 if (SYMBIAN_DEBUG)
85fbca6a
NC
138 fprintf (stderr, "IMPORT AS: No mem for new rename node\n");
139 return FALSE;
140 }
141
142 if ((node->current_name = bfd_malloc (strlen (current_name) + 1)) == NULL)
143 {
63f2fc30 144 if (SYMBIAN_DEBUG)
85fbca6a
NC
145 fprintf (stderr, "IMPORT AS: No mem for current name field in rename node\n");
146 free (node);
147 return FALSE;
148 }
149 else
150 strcpy (node->current_name, current_name);
68ffbac6 151
85fbca6a
NC
152 if ((node->new_name = bfd_malloc (strlen (new_name) + 1)) == NULL)
153 {
63f2fc30 154 if (SYMBIAN_DEBUG)
85fbca6a
NC
155 fprintf (stderr, "IMPORT AS: No mem for new name field in rename node\n");
156 free (node->current_name);
157 free (node);
158 return FALSE;
159 }
160 else
161 strcpy (node->new_name, new_name);
162
163 node->next = rename_list;
164 node->current_hash = NULL;
165 node->new_symndx = 0;
166 rename_list = node;
167
168 new_hash = elf_link_hash_lookup (elf_hash_table (info), node->new_name, TRUE, FALSE, TRUE);
169 bfd_elf_link_record_dynamic_symbol (info, new_hash);
170 if (new_hash->root.type == bfd_link_hash_new)
171 new_hash->root.type = bfd_link_hash_undefined;
172
173 return TRUE;
174}
175
176
177static bfd_boolean
f075ee0c 178sh_symbian_import (bfd * abfd ATTRIBUTE_UNUSED, char * name)
85fbca6a 179{
63f2fc30 180 if (SYMBIAN_DEBUG)
85fbca6a
NC
181 fprintf (stderr, "IMPORT '%s'\n", name);
182
183 /* XXX: Generate an import somehow ? */
184
185 return TRUE;
186}
187
188static bfd_boolean
f075ee0c 189sh_symbian_export (bfd * abfd ATTRIBUTE_UNUSED, char * name)
85fbca6a 190{
63f2fc30 191 if (SYMBIAN_DEBUG)
85fbca6a
NC
192 fprintf (stderr, "EXPORT '%s'\n", name);
193
194 /* XXX: Generate an export somehow ? */
195
196 return TRUE;
197}
198
199/* Process any magic embedded commands in the .directive. section.
200 Returns TRUE upon sucecss, but if it fails it sets bfd_error and
201 returns FALSE. */
202
203static bfd_boolean
204sh_symbian_process_embedded_commands (struct bfd_link_info *info, bfd * abfd,
205 asection * sec, bfd_byte * contents)
206{
f075ee0c
AM
207 char *s;
208 char *e;
85fbca6a
NC
209 bfd_boolean result = TRUE;
210 bfd_size_type sz = sec->rawsize ? sec->rawsize : sec->size;
211
f075ee0c 212 for (s = (char *) contents, e = s + sz; s < e;)
85fbca6a 213 {
f075ee0c 214 char * directive = s;
85fbca6a
NC
215
216 switch (*s)
217 {
218 /* I want to use "case DIRECTIVE_HEADER [0]:" here but gcc won't let me :-( */
219 case '#':
220 if (strcmp (s, DIRECTIVE_HEADER))
221 result = FALSE;
222 else
223 /* Just ignore the header.
224 XXX: Strictly speaking we ought to check that the header
225 is present and that it is the first thing in the file. */
226 s += strlen (DIRECTIVE_HEADER) + 1;
227 break;
228
229 case 'I':
0112cd26 230 if (! CONST_STRNEQ (s, DIRECTIVE_IMPORT))
85fbca6a
NC
231 result = FALSE;
232 else
233 {
f075ee0c
AM
234 char * new_name;
235 char * new_name_end;
236 char name_end_char;
85fbca6a
NC
237
238 /* Skip the IMPORT directive. */
239 s += strlen (DIRECTIVE_IMPORT);
240
241 new_name = s;
242 /* Find the end of the new name. */
243 while (s < e && *s != ' ' && *s != '\n')
244 ++ s;
245 if (s >= e)
246 {
247 /* We have reached the end of the .directive section
248 without encountering a string terminator. This is
249 allowed for IMPORT directives. */
250 new_name_end = e - 1;
251 name_end_char = * new_name_end;
252 * new_name_end = 0;
253 result = sh_symbian_import (abfd, new_name);
254 * new_name_end = name_end_char;
255 break;
256 }
257
258 /* Remember where the name ends. */
259 new_name_end = s;
260 /* Skip any whitespace before the 'AS'. */
261 SKIP_WHILE (s, e, ' ', "IMPORT: Name just followed by spaces");
262 /* Terminate the new name. (Do this after skiping...) */
263 name_end_char = * new_name_end;
264 * new_name_end = 0;
265
0112cd26
NC
266 /* Check to see if 'AS '... is present. If so we have an
267 IMPORT AS directive, otherwise we have an IMPORT directive. */
268 if (! CONST_STRNEQ (s, DIRECTIVE_AS))
85fbca6a
NC
269 {
270 /* Skip the new-line at the end of the name. */
63f2fc30 271 if (SYMBIAN_DEBUG && name_end_char != '\n')
85fbca6a
NC
272 fprintf (stderr, "IMPORT: No newline at end of directive\n");
273 else
274 s ++;
275
276 result = sh_symbian_import (abfd, new_name);
277
278 /* Skip past the NUL character. */
279 if (* s ++ != 0)
280 {
63f2fc30 281 if (SYMBIAN_DEBUG)
85fbca6a
NC
282 fprintf (stderr, "IMPORT: No NUL at end of directive\n");
283 }
284 }
285 else
286 {
f075ee0c
AM
287 char * current_name;
288 char * current_name_end;
289 char current_name_end_char;
85fbca6a
NC
290
291 /* Skip the 'AS '. */
292 s += strlen (DIRECTIVE_AS);
293 /* Skip any white space after the 'AS '. */
294 SKIP_WHILE (s, e, ' ', "IMPORT AS: Nothing after AS");
295 current_name = s;
296 /* Find the end of the current name. */
297 SKIP_UNTIL2 (s, e, ' ', '\n', "IMPORT AS: No newline at the end of the current name");
298 /* Skip (backwards) over spaces at the end of the current name. */
299 current_name_end = s;
300 current_name_end_char = * current_name_end;
301
302 SKIP_WHILE (s, e, ' ', "IMPORT AS: Current name just followed by spaces");
303 /* Skip past the newline character. */
304 if (* s ++ != '\n')
63f2fc30 305 if (SYMBIAN_DEBUG)
85fbca6a
NC
306 fprintf (stderr, "IMPORT AS: No newline at end of directive\n");
307
308 /* Terminate the current name after having performed the skips. */
309 * current_name_end = 0;
310
311 result = sh_symbian_import_as (info, abfd, current_name, new_name);
312
313 /* The next character should be a NUL. */
314 if (* s != 0)
315 {
63f2fc30 316 if (SYMBIAN_DEBUG)
85fbca6a
NC
317 fprintf (stderr, "IMPORT AS: Junk at end of directive\n");
318 result = FALSE;
319 }
320 s ++;
321
322 * current_name_end = current_name_end_char;
323 }
324
325 /* Restore the characters we overwrote, since
326 the .directive section will be emitted. */
327 * new_name_end = name_end_char;
328 }
329 break;
330
331 case 'E':
0112cd26 332 if (! CONST_STRNEQ (s, DIRECTIVE_EXPORT))
85fbca6a
NC
333 result = FALSE;
334 else
335 {
f075ee0c
AM
336 char * name;
337 char * name_end;
338 char name_end_char;
85fbca6a
NC
339
340 /* Skip the directive. */
341 s += strlen (DIRECTIVE_EXPORT);
342 name = s;
343 /* Find the end of the name to be exported. */
344 SKIP_UNTIL (s, e, '\n', "EXPORT: no newline at end of directive");
345 /* Skip (backwards) over spaces at end of exported name. */
346 for (name_end = s; name_end[-1] == ' '; name_end --)
347 ;
348 /* name_end now points at the first character after the
349 end of the exported name, so we can termiante it */
350 name_end_char = * name_end;
351 * name_end = 0;
352 /* Skip passed the newline character. */
353 s ++;
354
355 result = sh_symbian_export (abfd, name);
356
357 /* The next character should be a NUL. */
358 if (* s != 0)
359 {
63f2fc30 360 if (SYMBIAN_DEBUG)
85fbca6a
NC
361 fprintf (stderr, "EXPORT: Junk at end of directive\n");
362 result = FALSE;
363 }
364 s++;
365
366 /* Restore the character we deleted. */
367 * name_end = name_end_char;
368 }
369 break;
370
371 default:
372 result = FALSE;
373 break;
374 }
375
376 if (! result)
377 {
63f2fc30 378 if (SYMBIAN_DEBUG)
f60ca5e3
AM
379 fprintf (stderr, "offset into .directive section: %ld\n",
380 (long) (directive - (char *) contents));
68ffbac6 381
85fbca6a 382 bfd_set_error (bfd_error_invalid_operation);
695344c0 383 /* xgettext:c-format */
d003868e
AM
384 _bfd_error_handler (_("%B: Unrecognised .directive command: %s"),
385 abfd, directive);
85fbca6a
NC
386 break;
387 }
388 }
389
390 return result;
391}
392
393
394/* Scan a bfd for a .directive section, and if found process it.
395 Returns TRUE upon success, FALSE otherwise. */
85fbca6a 396
7d9616d7
AM
397static bfd_boolean
398sh_symbian_process_directives (bfd *abfd, struct bfd_link_info *info)
85fbca6a
NC
399{
400 bfd_boolean result = FALSE;
401 bfd_byte * contents;
402 asection * sec = bfd_get_section_by_name (abfd, ".directive");
403 bfd_size_type sz;
404
405 if (!sec)
406 return TRUE;
407
408 sz = sec->rawsize ? sec->rawsize : sec->size;
409 contents = bfd_malloc (sz);
410
411 if (!contents)
412 bfd_set_error (bfd_error_no_memory);
68ffbac6 413 else
85fbca6a
NC
414 {
415 if (bfd_get_section_contents (abfd, sec, contents, 0, sz))
416 result = sh_symbian_process_embedded_commands (info, abfd, sec, contents);
417 free (contents);
418 }
419
420 return result;
421}
422
423/* Intercept the normal sh_relocate_section() function
424 and magle the relocs to allow for symbol renaming. */
425
426static bfd_boolean
427sh_symbian_relocate_section (bfd * output_bfd,
428 struct bfd_link_info * info,
429 bfd * input_bfd,
430 asection * input_section,
431 bfd_byte * contents,
432 Elf_Internal_Rela * relocs,
433 Elf_Internal_Sym * local_syms,
434 asection ** local_sections)
435{
436 /* When performing a final link we implement the IMPORT AS directives. */
0e1862bb 437 if (!bfd_link_relocatable (info))
85fbca6a
NC
438 {
439 Elf_Internal_Rela * rel;
440 Elf_Internal_Rela * relend;
441 Elf_Internal_Shdr * symtab_hdr;
442 struct elf_link_hash_entry ** sym_hashes;
443 struct elf_link_hash_entry ** sym_hashes_end;
444 struct elf_link_hash_table * hash_table;
445 symbol_rename * ptr;
446 bfd_size_type num_global_syms;
447 unsigned long num_local_syms;
68ffbac6 448
85fbca6a 449 BFD_ASSERT (! elf_bad_symtab (input_bfd));
68ffbac6 450
85fbca6a
NC
451 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
452 hash_table = elf_hash_table (info);
453 num_local_syms = symtab_hdr->sh_info;
454 num_global_syms = symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
455 num_global_syms -= num_local_syms;
456 sym_hashes = elf_sym_hashes (input_bfd);
457 sym_hashes_end = sym_hashes + num_global_syms;
458
459 /* First scan the rename table, caching the hash entry and the new index. */
460 for (ptr = rename_list; ptr; ptr = ptr->next)
461 {
462 struct elf_link_hash_entry * new_hash;
463 struct elf_link_hash_entry ** h;
464
465 ptr->current_hash = elf_link_hash_lookup (hash_table, ptr->current_name, FALSE, FALSE, TRUE);
466
467 if (ptr->current_hash == NULL)
468 {
63f2fc30 469 if (SYMBIAN_DEBUG)
85fbca6a
NC
470 fprintf (stderr, "IMPORT AS: current symbol '%s' does not exist\n", ptr->current_name);
471 continue;
472 }
68ffbac6 473
8a56bd02
AM
474 new_hash = elf_link_hash_lookup (hash_table, ptr->new_name,
475 FALSE, FALSE, TRUE);
85fbca6a
NC
476 /* If we could not find the symbol then it is a new, undefined symbol.
477 Symbian want this behaviour - ie they want to be able to rename the
478 reference in a reloc from one undefined symbol to another, new and
479 undefined symbol. So we create that symbol here. */
480 if (new_hash == NULL)
481 {
8a56bd02
AM
482 struct bfd_link_hash_entry *bh = NULL;
483 bfd_boolean collect = get_elf_backend_data (input_bfd)->collect;
484 if (_bfd_generic_link_add_one_symbol (info, input_bfd,
485 ptr->new_name, BSF_GLOBAL,
486 bfd_und_section_ptr, 0,
487 NULL, FALSE, collect,
488 &bh))
85fbca6a 489 {
8a56bd02
AM
490 new_hash = (struct elf_link_hash_entry *) bh;
491 new_hash->type = STT_FUNC;
492 new_hash->non_elf = 0;
85fbca6a 493
8a56bd02
AM
494 if (SYMBIAN_DEBUG)
495 fprintf (stderr, "Created new symbol %s\n", ptr->new_name);
496 }
497 }
85fbca6a 498
8a56bd02
AM
499 if (new_hash == NULL)
500 {
695344c0 501 /* xgettext:c-format */
8a56bd02
AM
502 _bfd_error_handler (_("%B: Failed to add renamed symbol %s"),
503 input_bfd, ptr->new_name);
504 continue;
85fbca6a
NC
505 }
506
507 /* Convert the new_hash value into a index into the table of symbol hashes. */
508 for (h = sym_hashes; h < sym_hashes_end; h ++)
509 {
510 if (* h == new_hash)
511 {
512 ptr->new_symndx = h - sym_hashes + num_local_syms;
63f2fc30 513 if (SYMBIAN_DEBUG)
85fbca6a
NC
514 fprintf (stderr, "Converted new hash to index of %ld\n", ptr->new_symndx);
515 break;
516 }
517 }
518 /* If the new symbol is not in the hash table then it must be
519 because it is one of the newly created undefined symbols
520 manufactured above. So we extend the sym has table here to
521 include this extra symbol. */
522 if (h == sym_hashes_end)
523 {
524 struct elf_link_hash_entry ** new_sym_hashes;
525
526 /* This is not very efficient, but it works. */
527 ++ num_global_syms;
528 new_sym_hashes = bfd_alloc (input_bfd, num_global_syms * sizeof * sym_hashes);
529 if (new_sym_hashes == NULL)
530 {
63f2fc30 531 if (SYMBIAN_DEBUG)
85fbca6a
NC
532 fprintf (stderr, "Out of memory extending hash table\n");
533 continue;
534 }
535 memcpy (new_sym_hashes, sym_hashes, (num_global_syms - 1) * sizeof * sym_hashes);
536 new_sym_hashes[num_global_syms - 1] = new_hash;
537 elf_sym_hashes (input_bfd) = sym_hashes = new_sym_hashes;
538 sym_hashes_end = sym_hashes + num_global_syms;
539 symtab_hdr->sh_size = (num_global_syms + num_local_syms) * sizeof (Elf32_External_Sym);
540
541 ptr->new_symndx = num_global_syms - 1 + num_local_syms;
542
63f2fc30 543 if (SYMBIAN_DEBUG)
85fbca6a
NC
544 fprintf (stderr, "Extended symbol hash table to insert new symbol as index %ld\n",
545 ptr->new_symndx);
546 }
547 }
548
549 /* Walk the reloc list looking for references to renamed symbols.
550 When we find one, we alter the index in the reloc to point to the new symbol. */
551 for (rel = relocs, relend = relocs + input_section->reloc_count;
552 rel < relend;
553 rel ++)
554 {
555 int r_type;
556 unsigned long r_symndx;
557 struct elf_link_hash_entry * h;
68ffbac6 558
85fbca6a
NC
559 r_symndx = ELF32_R_SYM (rel->r_info);
560 r_type = ELF32_R_TYPE (rel->r_info);
561
562 /* Ignore unused relocs. */
563 if ((r_type >= (int) R_SH_GNU_VTINHERIT
564 && r_type <= (int) R_SH_LABEL)
565 || r_type == (int) R_SH_NONE
566 || r_type < 0
567 || r_type >= R_SH_max)
568 continue;
569
570 /* Ignore relocs against local symbols. */
571 if (r_symndx < num_local_syms)
572 continue;
573
574 BFD_ASSERT (r_symndx < (num_global_syms + num_local_syms));
575 h = sym_hashes[r_symndx - num_local_syms];
576 BFD_ASSERT (h != NULL);
577
578 while ( h->root.type == bfd_link_hash_indirect
579 || h->root.type == bfd_link_hash_warning)
580 h = (struct elf_link_hash_entry *) h->root.u.i.link;
581
582 /* If the symbol is defined there is no need to rename it.
583 XXX - is this true ? */
584 if ( h->root.type == bfd_link_hash_defined
585 || h->root.type == bfd_link_hash_defweak
586 || h->root.type == bfd_link_hash_undefweak)
587 continue;
588
589 for (ptr = rename_list; ptr; ptr = ptr->next)
590 if (h == ptr->current_hash)
591 {
592 BFD_ASSERT (ptr->new_symndx);
63f2fc30 593 if (SYMBIAN_DEBUG)
85fbca6a 594 fprintf (stderr, "convert reloc %lx from using index %ld to using index %ld\n",
0af1713e
AM
595 (unsigned long) rel->r_info,
596 (long) ELF32_R_SYM (rel->r_info), ptr->new_symndx);
85fbca6a
NC
597 rel->r_info = ELF32_R_INFO (ptr->new_symndx, r_type);
598 break;
599 }
600 }
601 }
68ffbac6 602
85fbca6a
NC
603 return sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
604 contents, relocs, local_syms, local_sections);
605}
606
6d00b590 607#define TARGET_LITTLE_SYM sh_elf32_symbian_le_vec
85fbca6a
NC
608#define TARGET_LITTLE_NAME "elf32-shl-symbian"
609
610#undef elf_backend_relocate_section
611#define elf_backend_relocate_section sh_symbian_relocate_section
612#undef elf_backend_check_directives
7d9616d7 613#define elf_backend_check_directives sh_symbian_process_directives
85fbca6a
NC
614
615#include "elf32-target.h"
This page took 0.723918 seconds and 4 git commands to generate.