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