assorted target messages
[external/binutils.git] / bfd / elf32-sh-symbian.c
1 /* Renesas / SuperH specific support for Symbian 32-bit ELF files
2    Copyright (C) 2004-2018 Free Software Foundation, Inc.
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
9    the Free Software Foundation; either version 3 of the License, or
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
19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21
22
23 /* Stop elf32-sh.c from defining any target vectors.  */
24 #define SH_TARGET_ALREADY_DEFINED
25 #define sh_find_elf_flags           sh_symbian_find_elf_flags
26 #define sh_elf_get_flags_from_mach  sh_symbian_elf_get_flags_from_mach
27 #include "elf32-sh.c"
28
29
30 //#define SYMBIAN_DEBUG 1
31 #define SYMBIAN_DEBUG 0
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
40    reached and SYMBIAN_DEBUG is enabled then the error message 'm'
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         {                                                       \
49           if (SYMBIAN_DEBUG)                                    \
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         {                                                       \
67           if (SYMBIAN_DEBUG)                                    \
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'
78    is reached and SYMBIAN_DEBUG is enabled then the error message
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         {                                                       \
87           if (SYMBIAN_DEBUG)                                    \
88             fprintf (stderr, "Corrupt directive: %s\n", m);     \
89           result = FALSE;                                       \
90         }                                                       \
91     }                                                           \
92   while (0);                                                    \
93   if (!result)                                                  \
94      break;
95
96
97 typedef struct symbol_rename
98 {
99   struct symbol_rename *       next;
100   char *                       current_name;
101   char *                       new_name;
102   struct elf_link_hash_entry * current_hash;
103   unsigned long                new_symndx;
104 }
105 symbol_rename;
106
107 static symbol_rename * rename_list = NULL;
108
109 /* Accumulate a list of symbols to be renamed.  */
110
111 static bfd_boolean
112 sh_symbian_import_as (struct bfd_link_info *info, bfd * abfd,
113                       char * current_name, char * new_name)
114 {
115   struct elf_link_hash_entry * new_hash;
116   symbol_rename * node;
117
118   if (SYMBIAN_DEBUG)
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);
129         /* xgettext:c-format */
130         _bfd_error_handler (_("%pB: IMPORT AS directive for %s conceals previous IMPORT AS"),
131                             abfd, current_name);
132         return FALSE;
133       }
134
135   if ((node = bfd_malloc (sizeof * node)) == NULL)
136     {
137       if (SYMBIAN_DEBUG)
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     {
144       if (SYMBIAN_DEBUG)
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);
151
152   if ((node->new_name = bfd_malloc (strlen (new_name) + 1)) == NULL)
153     {
154       if (SYMBIAN_DEBUG)
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
177 static bfd_boolean
178 sh_symbian_import (bfd * abfd ATTRIBUTE_UNUSED, char * name)
179 {
180   if (SYMBIAN_DEBUG)
181     fprintf (stderr, "IMPORT '%s'\n", name);
182
183   /* XXX: Generate an import somehow ?  */
184
185   return TRUE;
186 }
187
188 static bfd_boolean
189 sh_symbian_export (bfd * abfd ATTRIBUTE_UNUSED, char * name)
190 {
191   if (SYMBIAN_DEBUG)
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
203 static bfd_boolean
204 sh_symbian_process_embedded_commands (struct bfd_link_info *info, bfd * abfd,
205                                       asection * sec, bfd_byte * contents)
206 {
207   char *s;
208   char *e;
209   bfd_boolean result = TRUE;
210   bfd_size_type sz = sec->rawsize ? sec->rawsize : sec->size;
211
212   for (s = (char *) contents, e = s + sz; s < e;)
213     {
214       char * directive = s;
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':
230           if (! CONST_STRNEQ (s, DIRECTIVE_IMPORT))
231             result = FALSE;
232           else
233             {
234               char * new_name;
235               char * new_name_end;
236               char   name_end_char;
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
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))
269                 {
270                   /* Skip the new-line at the end of the name.  */
271                   if (SYMBIAN_DEBUG && name_end_char != '\n')
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                     {
281                       if (SYMBIAN_DEBUG)
282                         fprintf (stderr, "IMPORT: No NUL at end of directive\n");
283                     }
284                 }
285               else
286                 {
287                   char * current_name;
288                   char * current_name_end;
289                   char   current_name_end_char;
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')
305                     if (SYMBIAN_DEBUG)
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                     {
316                       if (SYMBIAN_DEBUG)
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':
332           if (! CONST_STRNEQ (s, DIRECTIVE_EXPORT))
333             result = FALSE;
334           else
335             {
336               char * name;
337               char * name_end;
338               char   name_end_char;
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                 {
360                   if (SYMBIAN_DEBUG)
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         {
378           if (SYMBIAN_DEBUG)
379             fprintf (stderr, "offset into .directive section: %ld\n",
380                      (long) (directive - (char *) contents));
381
382           bfd_set_error (bfd_error_invalid_operation);
383           /* xgettext:c-format */
384           _bfd_error_handler (_("%pB: unrecognized .directive command: %s"),
385                               abfd, directive);
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.  */
396
397 static bfd_boolean
398 sh_symbian_process_directives (bfd *abfd, struct bfd_link_info *info)
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);
413   else
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
426 static bfd_boolean
427 sh_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.  */
437   if (!bfd_link_relocatable (info))
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;
448
449       BFD_ASSERT (! elf_bad_symtab (input_bfd));
450
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             {
469               if (SYMBIAN_DEBUG)
470                 fprintf (stderr, "IMPORT AS: current symbol '%s' does not exist\n", ptr->current_name);
471               continue;
472             }
473
474           new_hash = elf_link_hash_lookup (hash_table, ptr->new_name,
475                                            FALSE, FALSE, TRUE);
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             {
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))
489                 {
490                   new_hash = (struct elf_link_hash_entry *) bh;
491                   new_hash->type = STT_FUNC;
492                   new_hash->non_elf = 0;
493
494                   if (SYMBIAN_DEBUG)
495                     fprintf (stderr, "Created new symbol %s\n", ptr->new_name);
496                 }
497             }
498
499           if (new_hash == NULL)
500             {
501               /* xgettext:c-format */
502               _bfd_error_handler (_("%pB: failed to add renamed symbol %s"),
503                                   input_bfd, ptr->new_name);
504               continue;
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;
513                   if (SYMBIAN_DEBUG)
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                 {
531                   if (SYMBIAN_DEBUG)
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
543               if (SYMBIAN_DEBUG)
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;
558
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);
593                 if (SYMBIAN_DEBUG)
594                   fprintf (stderr, "convert reloc %lx from using index %ld to using index %ld\n",
595                            (unsigned long) rel->r_info,
596                            (long) ELF32_R_SYM (rel->r_info), ptr->new_symndx);
597                 rel->r_info = ELF32_R_INFO (ptr->new_symndx, r_type);
598                 break;
599               }
600         }
601     }
602
603   return sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
604                                   contents, relocs, local_syms, local_sections);
605 }
606
607 #define TARGET_LITTLE_SYM       sh_elf32_symbian_le_vec
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
613 #define elf_backend_check_directives    sh_symbian_process_directives
614
615 #include "elf32-target.h"