Update ARC instruction data-base.
[deliverable/binutils-gdb.git] / bfd / elf32-sh-symbian.c
CommitLineData
85fbca6a 1/* Renesas / SuperH specific support for Symbian 32-bit ELF files
6f2750fe 2 Copyright (C) 2004-2016 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);
d003868e
AM
129 _bfd_error_handler (_("%B: IMPORT AS directive for %s conceals previous IMPORT AS"),
130 abfd, current_name);
68ffbac6 131 return FALSE;
85fbca6a
NC
132 }
133
134 if ((node = bfd_malloc (sizeof * node)) == NULL)
135 {
63f2fc30 136 if (SYMBIAN_DEBUG)
85fbca6a
NC
137 fprintf (stderr, "IMPORT AS: No mem for new rename node\n");
138 return FALSE;
139 }
140
141 if ((node->current_name = bfd_malloc (strlen (current_name) + 1)) == NULL)
142 {
63f2fc30 143 if (SYMBIAN_DEBUG)
85fbca6a
NC
144 fprintf (stderr, "IMPORT AS: No mem for current name field in rename node\n");
145 free (node);
146 return FALSE;
147 }
148 else
149 strcpy (node->current_name, current_name);
68ffbac6 150
85fbca6a
NC
151 if ((node->new_name = bfd_malloc (strlen (new_name) + 1)) == NULL)
152 {
63f2fc30 153 if (SYMBIAN_DEBUG)
85fbca6a
NC
154 fprintf (stderr, "IMPORT AS: No mem for new name field in rename node\n");
155 free (node->current_name);
156 free (node);
157 return FALSE;
158 }
159 else
160 strcpy (node->new_name, new_name);
161
162 node->next = rename_list;
163 node->current_hash = NULL;
164 node->new_symndx = 0;
165 rename_list = node;
166
167 new_hash = elf_link_hash_lookup (elf_hash_table (info), node->new_name, TRUE, FALSE, TRUE);
168 bfd_elf_link_record_dynamic_symbol (info, new_hash);
169 if (new_hash->root.type == bfd_link_hash_new)
170 new_hash->root.type = bfd_link_hash_undefined;
171
172 return TRUE;
173}
174
175
176static bfd_boolean
f075ee0c 177sh_symbian_import (bfd * abfd ATTRIBUTE_UNUSED, char * name)
85fbca6a 178{
63f2fc30 179 if (SYMBIAN_DEBUG)
85fbca6a
NC
180 fprintf (stderr, "IMPORT '%s'\n", name);
181
182 /* XXX: Generate an import somehow ? */
183
184 return TRUE;
185}
186
187static bfd_boolean
f075ee0c 188sh_symbian_export (bfd * abfd ATTRIBUTE_UNUSED, char * name)
85fbca6a 189{
63f2fc30 190 if (SYMBIAN_DEBUG)
85fbca6a
NC
191 fprintf (stderr, "EXPORT '%s'\n", name);
192
193 /* XXX: Generate an export somehow ? */
194
195 return TRUE;
196}
197
198/* Process any magic embedded commands in the .directive. section.
199 Returns TRUE upon sucecss, but if it fails it sets bfd_error and
200 returns FALSE. */
201
202static bfd_boolean
203sh_symbian_process_embedded_commands (struct bfd_link_info *info, bfd * abfd,
204 asection * sec, bfd_byte * contents)
205{
f075ee0c
AM
206 char *s;
207 char *e;
85fbca6a
NC
208 bfd_boolean result = TRUE;
209 bfd_size_type sz = sec->rawsize ? sec->rawsize : sec->size;
210
f075ee0c 211 for (s = (char *) contents, e = s + sz; s < e;)
85fbca6a 212 {
f075ee0c 213 char * directive = s;
85fbca6a
NC
214
215 switch (*s)
216 {
217 /* I want to use "case DIRECTIVE_HEADER [0]:" here but gcc won't let me :-( */
218 case '#':
219 if (strcmp (s, DIRECTIVE_HEADER))
220 result = FALSE;
221 else
222 /* Just ignore the header.
223 XXX: Strictly speaking we ought to check that the header
224 is present and that it is the first thing in the file. */
225 s += strlen (DIRECTIVE_HEADER) + 1;
226 break;
227
228 case 'I':
0112cd26 229 if (! CONST_STRNEQ (s, DIRECTIVE_IMPORT))
85fbca6a
NC
230 result = FALSE;
231 else
232 {
f075ee0c
AM
233 char * new_name;
234 char * new_name_end;
235 char name_end_char;
85fbca6a
NC
236
237 /* Skip the IMPORT directive. */
238 s += strlen (DIRECTIVE_IMPORT);
239
240 new_name = s;
241 /* Find the end of the new name. */
242 while (s < e && *s != ' ' && *s != '\n')
243 ++ s;
244 if (s >= e)
245 {
246 /* We have reached the end of the .directive section
247 without encountering a string terminator. This is
248 allowed for IMPORT directives. */
249 new_name_end = e - 1;
250 name_end_char = * new_name_end;
251 * new_name_end = 0;
252 result = sh_symbian_import (abfd, new_name);
253 * new_name_end = name_end_char;
254 break;
255 }
256
257 /* Remember where the name ends. */
258 new_name_end = s;
259 /* Skip any whitespace before the 'AS'. */
260 SKIP_WHILE (s, e, ' ', "IMPORT: Name just followed by spaces");
261 /* Terminate the new name. (Do this after skiping...) */
262 name_end_char = * new_name_end;
263 * new_name_end = 0;
264
0112cd26
NC
265 /* Check to see if 'AS '... is present. If so we have an
266 IMPORT AS directive, otherwise we have an IMPORT directive. */
267 if (! CONST_STRNEQ (s, DIRECTIVE_AS))
85fbca6a
NC
268 {
269 /* Skip the new-line at the end of the name. */
63f2fc30 270 if (SYMBIAN_DEBUG && name_end_char != '\n')
85fbca6a
NC
271 fprintf (stderr, "IMPORT: No newline at end of directive\n");
272 else
273 s ++;
274
275 result = sh_symbian_import (abfd, new_name);
276
277 /* Skip past the NUL character. */
278 if (* s ++ != 0)
279 {
63f2fc30 280 if (SYMBIAN_DEBUG)
85fbca6a
NC
281 fprintf (stderr, "IMPORT: No NUL at end of directive\n");
282 }
283 }
284 else
285 {
f075ee0c
AM
286 char * current_name;
287 char * current_name_end;
288 char current_name_end_char;
85fbca6a
NC
289
290 /* Skip the 'AS '. */
291 s += strlen (DIRECTIVE_AS);
292 /* Skip any white space after the 'AS '. */
293 SKIP_WHILE (s, e, ' ', "IMPORT AS: Nothing after AS");
294 current_name = s;
295 /* Find the end of the current name. */
296 SKIP_UNTIL2 (s, e, ' ', '\n', "IMPORT AS: No newline at the end of the current name");
297 /* Skip (backwards) over spaces at the end of the current name. */
298 current_name_end = s;
299 current_name_end_char = * current_name_end;
300
301 SKIP_WHILE (s, e, ' ', "IMPORT AS: Current name just followed by spaces");
302 /* Skip past the newline character. */
303 if (* s ++ != '\n')
63f2fc30 304 if (SYMBIAN_DEBUG)
85fbca6a
NC
305 fprintf (stderr, "IMPORT AS: No newline at end of directive\n");
306
307 /* Terminate the current name after having performed the skips. */
308 * current_name_end = 0;
309
310 result = sh_symbian_import_as (info, abfd, current_name, new_name);
311
312 /* The next character should be a NUL. */
313 if (* s != 0)
314 {
63f2fc30 315 if (SYMBIAN_DEBUG)
85fbca6a
NC
316 fprintf (stderr, "IMPORT AS: Junk at end of directive\n");
317 result = FALSE;
318 }
319 s ++;
320
321 * current_name_end = current_name_end_char;
322 }
323
324 /* Restore the characters we overwrote, since
325 the .directive section will be emitted. */
326 * new_name_end = name_end_char;
327 }
328 break;
329
330 case 'E':
0112cd26 331 if (! CONST_STRNEQ (s, DIRECTIVE_EXPORT))
85fbca6a
NC
332 result = FALSE;
333 else
334 {
f075ee0c
AM
335 char * name;
336 char * name_end;
337 char name_end_char;
85fbca6a
NC
338
339 /* Skip the directive. */
340 s += strlen (DIRECTIVE_EXPORT);
341 name = s;
342 /* Find the end of the name to be exported. */
343 SKIP_UNTIL (s, e, '\n', "EXPORT: no newline at end of directive");
344 /* Skip (backwards) over spaces at end of exported name. */
345 for (name_end = s; name_end[-1] == ' '; name_end --)
346 ;
347 /* name_end now points at the first character after the
348 end of the exported name, so we can termiante it */
349 name_end_char = * name_end;
350 * name_end = 0;
351 /* Skip passed the newline character. */
352 s ++;
353
354 result = sh_symbian_export (abfd, name);
355
356 /* The next character should be a NUL. */
357 if (* s != 0)
358 {
63f2fc30 359 if (SYMBIAN_DEBUG)
85fbca6a
NC
360 fprintf (stderr, "EXPORT: Junk at end of directive\n");
361 result = FALSE;
362 }
363 s++;
364
365 /* Restore the character we deleted. */
366 * name_end = name_end_char;
367 }
368 break;
369
370 default:
371 result = FALSE;
372 break;
373 }
374
375 if (! result)
376 {
63f2fc30 377 if (SYMBIAN_DEBUG)
f60ca5e3
AM
378 fprintf (stderr, "offset into .directive section: %ld\n",
379 (long) (directive - (char *) contents));
68ffbac6 380
85fbca6a 381 bfd_set_error (bfd_error_invalid_operation);
d003868e
AM
382 _bfd_error_handler (_("%B: Unrecognised .directive command: %s"),
383 abfd, directive);
85fbca6a
NC
384 break;
385 }
386 }
387
388 return result;
389}
390
391
392/* Scan a bfd for a .directive section, and if found process it.
393 Returns TRUE upon success, FALSE otherwise. */
85fbca6a 394
7d9616d7
AM
395static bfd_boolean
396sh_symbian_process_directives (bfd *abfd, struct bfd_link_info *info)
85fbca6a
NC
397{
398 bfd_boolean result = FALSE;
399 bfd_byte * contents;
400 asection * sec = bfd_get_section_by_name (abfd, ".directive");
401 bfd_size_type sz;
402
403 if (!sec)
404 return TRUE;
405
406 sz = sec->rawsize ? sec->rawsize : sec->size;
407 contents = bfd_malloc (sz);
408
409 if (!contents)
410 bfd_set_error (bfd_error_no_memory);
68ffbac6 411 else
85fbca6a
NC
412 {
413 if (bfd_get_section_contents (abfd, sec, contents, 0, sz))
414 result = sh_symbian_process_embedded_commands (info, abfd, sec, contents);
415 free (contents);
416 }
417
418 return result;
419}
420
421/* Intercept the normal sh_relocate_section() function
422 and magle the relocs to allow for symbol renaming. */
423
424static bfd_boolean
425sh_symbian_relocate_section (bfd * output_bfd,
426 struct bfd_link_info * info,
427 bfd * input_bfd,
428 asection * input_section,
429 bfd_byte * contents,
430 Elf_Internal_Rela * relocs,
431 Elf_Internal_Sym * local_syms,
432 asection ** local_sections)
433{
434 /* When performing a final link we implement the IMPORT AS directives. */
0e1862bb 435 if (!bfd_link_relocatable (info))
85fbca6a
NC
436 {
437 Elf_Internal_Rela * rel;
438 Elf_Internal_Rela * relend;
439 Elf_Internal_Shdr * symtab_hdr;
440 struct elf_link_hash_entry ** sym_hashes;
441 struct elf_link_hash_entry ** sym_hashes_end;
442 struct elf_link_hash_table * hash_table;
443 symbol_rename * ptr;
444 bfd_size_type num_global_syms;
445 unsigned long num_local_syms;
68ffbac6 446
85fbca6a 447 BFD_ASSERT (! elf_bad_symtab (input_bfd));
68ffbac6 448
85fbca6a
NC
449 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
450 hash_table = elf_hash_table (info);
451 num_local_syms = symtab_hdr->sh_info;
452 num_global_syms = symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
453 num_global_syms -= num_local_syms;
454 sym_hashes = elf_sym_hashes (input_bfd);
455 sym_hashes_end = sym_hashes + num_global_syms;
456
457 /* First scan the rename table, caching the hash entry and the new index. */
458 for (ptr = rename_list; ptr; ptr = ptr->next)
459 {
460 struct elf_link_hash_entry * new_hash;
461 struct elf_link_hash_entry ** h;
462
463 ptr->current_hash = elf_link_hash_lookup (hash_table, ptr->current_name, FALSE, FALSE, TRUE);
464
465 if (ptr->current_hash == NULL)
466 {
63f2fc30 467 if (SYMBIAN_DEBUG)
85fbca6a
NC
468 fprintf (stderr, "IMPORT AS: current symbol '%s' does not exist\n", ptr->current_name);
469 continue;
470 }
68ffbac6 471
8a56bd02
AM
472 new_hash = elf_link_hash_lookup (hash_table, ptr->new_name,
473 FALSE, FALSE, TRUE);
85fbca6a
NC
474 /* If we could not find the symbol then it is a new, undefined symbol.
475 Symbian want this behaviour - ie they want to be able to rename the
476 reference in a reloc from one undefined symbol to another, new and
477 undefined symbol. So we create that symbol here. */
478 if (new_hash == NULL)
479 {
8a56bd02
AM
480 struct bfd_link_hash_entry *bh = NULL;
481 bfd_boolean collect = get_elf_backend_data (input_bfd)->collect;
482 if (_bfd_generic_link_add_one_symbol (info, input_bfd,
483 ptr->new_name, BSF_GLOBAL,
484 bfd_und_section_ptr, 0,
485 NULL, FALSE, collect,
486 &bh))
85fbca6a 487 {
8a56bd02
AM
488 new_hash = (struct elf_link_hash_entry *) bh;
489 new_hash->type = STT_FUNC;
490 new_hash->non_elf = 0;
85fbca6a 491
8a56bd02
AM
492 if (SYMBIAN_DEBUG)
493 fprintf (stderr, "Created new symbol %s\n", ptr->new_name);
494 }
495 }
85fbca6a 496
8a56bd02
AM
497 if (new_hash == NULL)
498 {
499 _bfd_error_handler (_("%B: Failed to add renamed symbol %s"),
500 input_bfd, ptr->new_name);
501 continue;
85fbca6a
NC
502 }
503
504 /* Convert the new_hash value into a index into the table of symbol hashes. */
505 for (h = sym_hashes; h < sym_hashes_end; h ++)
506 {
507 if (* h == new_hash)
508 {
509 ptr->new_symndx = h - sym_hashes + num_local_syms;
63f2fc30 510 if (SYMBIAN_DEBUG)
85fbca6a
NC
511 fprintf (stderr, "Converted new hash to index of %ld\n", ptr->new_symndx);
512 break;
513 }
514 }
515 /* If the new symbol is not in the hash table then it must be
516 because it is one of the newly created undefined symbols
517 manufactured above. So we extend the sym has table here to
518 include this extra symbol. */
519 if (h == sym_hashes_end)
520 {
521 struct elf_link_hash_entry ** new_sym_hashes;
522
523 /* This is not very efficient, but it works. */
524 ++ num_global_syms;
525 new_sym_hashes = bfd_alloc (input_bfd, num_global_syms * sizeof * sym_hashes);
526 if (new_sym_hashes == NULL)
527 {
63f2fc30 528 if (SYMBIAN_DEBUG)
85fbca6a
NC
529 fprintf (stderr, "Out of memory extending hash table\n");
530 continue;
531 }
532 memcpy (new_sym_hashes, sym_hashes, (num_global_syms - 1) * sizeof * sym_hashes);
533 new_sym_hashes[num_global_syms - 1] = new_hash;
534 elf_sym_hashes (input_bfd) = sym_hashes = new_sym_hashes;
535 sym_hashes_end = sym_hashes + num_global_syms;
536 symtab_hdr->sh_size = (num_global_syms + num_local_syms) * sizeof (Elf32_External_Sym);
537
538 ptr->new_symndx = num_global_syms - 1 + num_local_syms;
539
63f2fc30 540 if (SYMBIAN_DEBUG)
85fbca6a
NC
541 fprintf (stderr, "Extended symbol hash table to insert new symbol as index %ld\n",
542 ptr->new_symndx);
543 }
544 }
545
546 /* Walk the reloc list looking for references to renamed symbols.
547 When we find one, we alter the index in the reloc to point to the new symbol. */
548 for (rel = relocs, relend = relocs + input_section->reloc_count;
549 rel < relend;
550 rel ++)
551 {
552 int r_type;
553 unsigned long r_symndx;
554 struct elf_link_hash_entry * h;
68ffbac6 555
85fbca6a
NC
556 r_symndx = ELF32_R_SYM (rel->r_info);
557 r_type = ELF32_R_TYPE (rel->r_info);
558
559 /* Ignore unused relocs. */
560 if ((r_type >= (int) R_SH_GNU_VTINHERIT
561 && r_type <= (int) R_SH_LABEL)
562 || r_type == (int) R_SH_NONE
563 || r_type < 0
564 || r_type >= R_SH_max)
565 continue;
566
567 /* Ignore relocs against local symbols. */
568 if (r_symndx < num_local_syms)
569 continue;
570
571 BFD_ASSERT (r_symndx < (num_global_syms + num_local_syms));
572 h = sym_hashes[r_symndx - num_local_syms];
573 BFD_ASSERT (h != NULL);
574
575 while ( h->root.type == bfd_link_hash_indirect
576 || h->root.type == bfd_link_hash_warning)
577 h = (struct elf_link_hash_entry *) h->root.u.i.link;
578
579 /* If the symbol is defined there is no need to rename it.
580 XXX - is this true ? */
581 if ( h->root.type == bfd_link_hash_defined
582 || h->root.type == bfd_link_hash_defweak
583 || h->root.type == bfd_link_hash_undefweak)
584 continue;
585
586 for (ptr = rename_list; ptr; ptr = ptr->next)
587 if (h == ptr->current_hash)
588 {
589 BFD_ASSERT (ptr->new_symndx);
63f2fc30 590 if (SYMBIAN_DEBUG)
85fbca6a 591 fprintf (stderr, "convert reloc %lx from using index %ld to using index %ld\n",
0af1713e
AM
592 (unsigned long) rel->r_info,
593 (long) ELF32_R_SYM (rel->r_info), ptr->new_symndx);
85fbca6a
NC
594 rel->r_info = ELF32_R_INFO (ptr->new_symndx, r_type);
595 break;
596 }
597 }
598 }
68ffbac6 599
85fbca6a
NC
600 return sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
601 contents, relocs, local_syms, local_sections);
602}
603
6d00b590 604#define TARGET_LITTLE_SYM sh_elf32_symbian_le_vec
85fbca6a
NC
605#define TARGET_LITTLE_NAME "elf32-shl-symbian"
606
607#undef elf_backend_relocate_section
608#define elf_backend_relocate_section sh_symbian_relocate_section
609#undef elf_backend_check_directives
7d9616d7 610#define elf_backend_check_directives sh_symbian_process_directives
85fbca6a
NC
611
612#include "elf32-target.h"
This page took 0.999339 seconds and 4 git commands to generate.