Back to index

cell-binutils  2.17cvs20070401
elf32-sh-symbian.c
Go to the documentation of this file.
00001 /* Renesas / SuperH specific support for Symbian 32-bit ELF files
00002    Copyright 2004, 2005, 2006
00003    Free Software Foundation, Inc.
00004    Contributed by Red Hat
00005 
00006    This file is part of BFD, the Binary File Descriptor library.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00021 
00022 /* Stop elf32-sh.c from defining any target vectors.  */
00023 #define SH_TARGET_ALREADY_DEFINED
00024 #define sh_find_elf_flags           sh_symbian_find_elf_flags
00025 #define sh_elf_get_flags_from_mach  sh_symbian_elf_get_flags_from_mach 
00026 #include "elf32-sh.c"
00027 
00028 
00029 //#define SYMBIAN_DEBUG 1
00030 #define SYMBIAN_DEBUG 0
00031 
00032 #define DIRECTIVE_HEADER    "#<SYMEDIT>#\n"
00033 #define DIRECTIVE_IMPORT    "IMPORT "
00034 #define DIRECTIVE_EXPORT    "EXPORT "
00035 #define DIRECTIVE_AS        "AS "
00036 
00037 /* Macro to advance 's' until either it reaches 'e' or the
00038    character pointed to by 's' is equal to 'c'.  If 'e' is
00039    reached and SYMBIAN_DEBUG is enabled then the error message 'm'
00040    is displayed.  */
00041 #define SKIP_UNTIL(s,e,c,m)                             \
00042   do                                                    \
00043     {                                                   \
00044       while (s < e && *s != c)                                 \
00045        ++ s;                                            \
00046       if (s >= e)                                       \
00047        {                                                \
00048           if (SYMBIAN_DEBUG)                                   \
00049            fprintf (stderr, "Corrupt directive: %s\n", m);     \
00050          result = FALSE;                                \
00051        }                                                \
00052     }                                                   \
00053   while (0);                                            \
00054   if (!result)                                                 \
00055      break;
00056 
00057 /* Like SKIP_UNTIL except there are two terminator characters
00058    c1 and c2.  */
00059 #define SKIP_UNTIL2(s,e,c1,c2,m)                        \
00060   do                                                    \
00061     {                                                   \
00062       while (s < e && *s != c1 && *s != c2)                    \
00063        ++ s;                                            \
00064       if (s >= e)                                       \
00065        {                                                \
00066           if (SYMBIAN_DEBUG)                                   \
00067            fprintf (stderr, "Corrupt directive: %s\n", m);     \
00068          result = FALSE;                                \
00069        }                                                \
00070     }                                                   \
00071   while (0);                                            \
00072   if (!result)                                                 \
00073      break;
00074 
00075 /* Macro to advance 's' until either it reaches 'e' or the
00076    character pointed to by 's' is not equal to 'c'.  If 'e'
00077    is reached and SYMBIAN_DEBUG is enabled then the error message
00078    'm' is displayed.  */
00079 #define SKIP_WHILE(s,e,c,m)                             \
00080   do                                                    \
00081     {                                                   \
00082       while (s < e && *s == c)                                 \
00083        ++ s;                                            \
00084       if (s >= e)                                       \
00085        {                                                \
00086           if (SYMBIAN_DEBUG)                                   \
00087            fprintf (stderr, "Corrupt directive: %s\n", m);     \
00088          result = FALSE;                                \
00089        }                                                \
00090     }                                                   \
00091   while (0);                                            \
00092   if (!result)                                                 \
00093      break;
00094 
00095 
00096 typedef struct symbol_rename
00097 {
00098   struct symbol_rename *       next;
00099   char *                       current_name;
00100   char *                       new_name;
00101   struct elf_link_hash_entry * current_hash;
00102   unsigned long                new_symndx;
00103 }
00104 symbol_rename;
00105 
00106 static symbol_rename * rename_list = NULL;
00107 
00108 /* Accumulate a list of symbols to be renamed.  */
00109 
00110 static bfd_boolean
00111 sh_symbian_import_as (struct bfd_link_info *info, bfd * abfd,
00112                     char * current_name, char * new_name)
00113 {
00114   struct elf_link_hash_entry * new_hash;
00115   symbol_rename * node;
00116 
00117   if (SYMBIAN_DEBUG)
00118     fprintf (stderr, "IMPORT '%s' AS '%s'\n", current_name, new_name);
00119 
00120   for (node = rename_list; node; node = node->next)
00121     if (strcmp (node->current_name, current_name) == 0)
00122       {
00123        if (strcmp (node->new_name, new_name) == 0)
00124          /* Already added to rename list.  */
00125          return TRUE;
00126 
00127        bfd_set_error (bfd_error_invalid_operation);
00128        _bfd_error_handler (_("%B: IMPORT AS directive for %s conceals previous IMPORT AS"),
00129                          abfd, current_name);
00130        return FALSE;     
00131       }
00132 
00133   if ((node = bfd_malloc (sizeof * node)) == NULL)
00134     {
00135       if (SYMBIAN_DEBUG)
00136        fprintf (stderr, "IMPORT AS: No mem for new rename node\n");
00137       return FALSE;
00138     }
00139 
00140   if ((node->current_name = bfd_malloc (strlen (current_name) + 1)) == NULL)
00141     {
00142       if (SYMBIAN_DEBUG)
00143        fprintf (stderr, "IMPORT AS: No mem for current name field in rename node\n");
00144       free (node);
00145       return FALSE;
00146     }
00147   else
00148     strcpy (node->current_name, current_name);
00149   
00150   if ((node->new_name = bfd_malloc (strlen (new_name) + 1)) == NULL)
00151     {
00152       if (SYMBIAN_DEBUG)
00153        fprintf (stderr, "IMPORT AS: No mem for new name field in rename node\n");
00154       free (node->current_name);
00155       free (node);
00156       return FALSE;
00157     }
00158   else
00159     strcpy (node->new_name, new_name);
00160 
00161   node->next = rename_list;
00162   node->current_hash = NULL;
00163   node->new_symndx = 0;
00164   rename_list = node;
00165 
00166   new_hash = elf_link_hash_lookup (elf_hash_table (info), node->new_name, TRUE, FALSE, TRUE);
00167   bfd_elf_link_record_dynamic_symbol (info, new_hash);
00168   if (new_hash->root.type == bfd_link_hash_new)
00169     new_hash->root.type = bfd_link_hash_undefined;
00170 
00171   return TRUE;
00172 }
00173 
00174 
00175 static bfd_boolean
00176 sh_symbian_import (bfd * abfd ATTRIBUTE_UNUSED, char * name)
00177 {
00178   if (SYMBIAN_DEBUG)
00179     fprintf (stderr, "IMPORT '%s'\n", name);
00180 
00181   /* XXX: Generate an import somehow ?  */
00182 
00183   return TRUE;
00184 }
00185 
00186 static bfd_boolean
00187 sh_symbian_export (bfd * abfd ATTRIBUTE_UNUSED, char * name)
00188 {
00189   if (SYMBIAN_DEBUG)
00190     fprintf (stderr, "EXPORT '%s'\n", name);
00191 
00192   /* XXX: Generate an export somehow ?  */
00193 
00194   return TRUE;
00195 }
00196 
00197 /* Process any magic embedded commands in the .directive. section.
00198    Returns TRUE upon sucecss, but if it fails it sets bfd_error and
00199    returns FALSE.  */
00200 
00201 static bfd_boolean
00202 sh_symbian_process_embedded_commands (struct bfd_link_info *info, bfd * abfd,
00203                                   asection * sec, bfd_byte * contents)
00204 {
00205   char *s;
00206   char *e;
00207   bfd_boolean result = TRUE;
00208   bfd_size_type sz = sec->rawsize ? sec->rawsize : sec->size;
00209 
00210   for (s = (char *) contents, e = s + sz; s < e;)
00211     {
00212       char * directive = s;
00213 
00214       switch (*s)
00215        {
00216          /* I want to use "case DIRECTIVE_HEADER [0]:" here but gcc won't let me :-(  */
00217        case '#':
00218          if (strcmp (s, DIRECTIVE_HEADER))
00219            result = FALSE;
00220          else
00221            /* Just ignore the header.
00222               XXX: Strictly speaking we ought to check that the header
00223               is present and that it is the first thing in the file.  */
00224            s += strlen (DIRECTIVE_HEADER) + 1;
00225          break;
00226 
00227        case 'I':
00228          if (! CONST_STRNEQ (s, DIRECTIVE_IMPORT))
00229            result = FALSE;
00230          else
00231            {
00232              char * new_name;
00233              char * new_name_end;
00234              char   name_end_char;
00235 
00236              /* Skip the IMPORT directive.  */
00237              s += strlen (DIRECTIVE_IMPORT);
00238 
00239              new_name = s;
00240              /* Find the end of the new name.  */
00241              while (s < e && *s != ' ' && *s != '\n')
00242               ++ s;
00243              if (s >= e)
00244               {
00245                 /* We have reached the end of the .directive section
00246                    without encountering a string terminator.  This is
00247                    allowed for IMPORT directives.  */
00248                 new_name_end   = e - 1;
00249                 name_end_char  = * new_name_end;
00250                 * new_name_end = 0;
00251                 result = sh_symbian_import (abfd, new_name);
00252                 * new_name_end = name_end_char;
00253                 break;
00254               }
00255 
00256              /* Remember where the name ends.  */
00257              new_name_end = s;
00258              /* Skip any whitespace before the 'AS'.  */
00259              SKIP_WHILE (s, e, ' ', "IMPORT: Name just followed by spaces");
00260              /* Terminate the new name.  (Do this after skiping...)  */
00261              name_end_char = * new_name_end;
00262              * new_name_end = 0;
00263 
00264              /* Check to see if 'AS '... is present.  If so we have an
00265                IMPORT AS directive, otherwise we have an IMPORT directive.  */
00266              if (! CONST_STRNEQ (s, DIRECTIVE_AS))
00267               {
00268                 /* Skip the new-line at the end of the name.  */
00269                 if (SYMBIAN_DEBUG && name_end_char != '\n')
00270                   fprintf (stderr, "IMPORT: No newline at end of directive\n");
00271                 else
00272                   s ++;
00273 
00274                 result = sh_symbian_import (abfd, new_name);
00275 
00276                 /* Skip past the NUL character.  */
00277                 if (* s ++ != 0)
00278                   {
00279                     if (SYMBIAN_DEBUG)
00280                      fprintf (stderr, "IMPORT: No NUL at end of directive\n");
00281                   }
00282               }
00283              else
00284               {
00285                 char * current_name;
00286                 char * current_name_end;
00287                 char   current_name_end_char;
00288 
00289                 /* Skip the 'AS '.  */
00290                 s += strlen (DIRECTIVE_AS);
00291                 /* Skip any white space after the 'AS '.  */
00292                 SKIP_WHILE (s, e, ' ', "IMPORT AS: Nothing after AS");
00293                 current_name = s;
00294                 /* Find the end of the current name.  */
00295                 SKIP_UNTIL2 (s, e, ' ', '\n', "IMPORT AS: No newline at the end of the current name");
00296                 /* Skip (backwards) over spaces at the end of the current name.  */
00297                 current_name_end = s;
00298                 current_name_end_char = * current_name_end;
00299 
00300                 SKIP_WHILE (s, e, ' ', "IMPORT AS: Current name just followed by spaces");
00301                 /* Skip past the newline character.  */
00302                 if (* s ++ != '\n')
00303                   if (SYMBIAN_DEBUG)
00304                     fprintf (stderr, "IMPORT AS: No newline at end of directive\n");
00305 
00306                 /* Terminate the current name after having performed the skips.  */
00307                 * current_name_end = 0;
00308 
00309                 result = sh_symbian_import_as (info, abfd, current_name, new_name);
00310 
00311                 /* The next character should be a NUL.  */
00312                 if (* s != 0)
00313                   {
00314                     if (SYMBIAN_DEBUG)
00315                      fprintf (stderr, "IMPORT AS: Junk at end of directive\n");
00316                     result = FALSE;
00317                   }
00318                 s ++;
00319 
00320                 * current_name_end = current_name_end_char;
00321               }
00322 
00323              /* Restore the characters we overwrote, since
00324                the .directive section will be emitted.  */
00325              * new_name_end = name_end_char;
00326            }
00327          break;
00328 
00329        case 'E':
00330          if (! CONST_STRNEQ (s, DIRECTIVE_EXPORT))
00331            result = FALSE;
00332          else
00333            {
00334              char * name;
00335              char * name_end;
00336              char   name_end_char;
00337 
00338              /* Skip the directive.  */
00339              s += strlen (DIRECTIVE_EXPORT);
00340              name = s;
00341              /* Find the end of the name to be exported.  */
00342              SKIP_UNTIL (s, e, '\n', "EXPORT: no newline at end of directive");
00343              /* Skip (backwards) over spaces at end of exported name.  */
00344              for (name_end = s; name_end[-1] == ' '; name_end --)
00345               ;
00346              /* name_end now points at the first character after the
00347                end of the exported name, so we can termiante it  */
00348              name_end_char = * name_end;
00349              * name_end = 0;
00350              /* Skip passed the newline character.  */
00351              s ++;
00352 
00353              result = sh_symbian_export (abfd, name);
00354 
00355              /* The next character should be a NUL.  */
00356              if (* s != 0)
00357               {
00358                 if (SYMBIAN_DEBUG)
00359                   fprintf (stderr, "EXPORT: Junk at end of directive\n");
00360                 result = FALSE;
00361               }
00362              s++;
00363 
00364              /* Restore the character we deleted.  */
00365              * name_end = name_end_char;
00366            }
00367          break;
00368 
00369        default:
00370          result = FALSE;
00371          break;
00372        }
00373 
00374       if (! result)
00375        {
00376          if (SYMBIAN_DEBUG)
00377            fprintf (stderr, "offset into .directive section: %ld\n",
00378                    (long) (directive - (char *) contents));
00379          
00380          bfd_set_error (bfd_error_invalid_operation);
00381          _bfd_error_handler (_("%B: Unrecognised .directive command: %s"),
00382                            abfd, directive);
00383          break;
00384        }
00385     }
00386 
00387   return result;
00388 }
00389 
00390 
00391 /* Scan a bfd for a .directive section, and if found process it.
00392    Returns TRUE upon success, FALSE otherwise.  */
00393 bfd_boolean bfd_elf32_sh_symbian_process_directives (struct bfd_link_info *info, bfd * abfd);
00394 
00395 bfd_boolean
00396 bfd_elf32_sh_symbian_process_directives (struct bfd_link_info *info, bfd * abfd)
00397 {
00398   bfd_boolean result = FALSE;
00399   bfd_byte *  contents;
00400   asection *  sec = bfd_get_section_by_name (abfd, ".directive");
00401   bfd_size_type sz;
00402 
00403   if (!sec)
00404     return TRUE;
00405 
00406   sz = sec->rawsize ? sec->rawsize : sec->size;
00407   contents = bfd_malloc (sz);
00408 
00409   if (!contents)
00410     bfd_set_error (bfd_error_no_memory);
00411   else 
00412     {
00413       if (bfd_get_section_contents (abfd, sec, contents, 0, sz))
00414        result = sh_symbian_process_embedded_commands (info, abfd, sec, contents);
00415       free (contents);
00416     }
00417 
00418   return result;
00419 }
00420 
00421 /* Intercept the normal sh_relocate_section() function
00422    and magle the relocs to allow for symbol renaming.  */
00423 
00424 static bfd_boolean
00425 sh_symbian_relocate_section (bfd *                  output_bfd,
00426                           struct bfd_link_info * info,
00427                           bfd *                  input_bfd,
00428                           asection *             input_section,
00429                           bfd_byte *             contents,
00430                           Elf_Internal_Rela *    relocs,
00431                           Elf_Internal_Sym *     local_syms,
00432                           asection **            local_sections)
00433 {
00434   /* When performing a final link we implement the IMPORT AS directives.  */
00435   if (!info->relocatable)
00436     {
00437       Elf_Internal_Rela *            rel;
00438       Elf_Internal_Rela *            relend;
00439       Elf_Internal_Shdr *            symtab_hdr;
00440       struct elf_link_hash_entry **  sym_hashes;
00441       struct elf_link_hash_entry **  sym_hashes_end;
00442       struct elf_link_hash_table *   hash_table;
00443       symbol_rename *                ptr;
00444       bfd_size_type                  num_global_syms;
00445       unsigned long              num_local_syms;
00446       
00447       BFD_ASSERT (! elf_bad_symtab (input_bfd));
00448  
00449       symtab_hdr       = & elf_tdata (input_bfd)->symtab_hdr;
00450       hash_table       = elf_hash_table (info);
00451       num_local_syms   = symtab_hdr->sh_info;
00452       num_global_syms  = symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
00453       num_global_syms -= num_local_syms;
00454       sym_hashes       = elf_sym_hashes (input_bfd);
00455       sym_hashes_end   = sym_hashes + num_global_syms;
00456 
00457       /* First scan the rename table, caching the hash entry and the new index.  */
00458       for (ptr = rename_list; ptr; ptr = ptr->next)
00459        {
00460          struct elf_link_hash_entry *   new_hash;
00461          struct elf_link_hash_entry **  h;
00462 
00463          ptr->current_hash = elf_link_hash_lookup (hash_table, ptr->current_name, FALSE, FALSE, TRUE);
00464 
00465          if (ptr->current_hash == NULL)
00466            {
00467              if (SYMBIAN_DEBUG)
00468               fprintf (stderr, "IMPORT AS: current symbol '%s' does not exist\n", ptr->current_name);
00469              continue;
00470            }
00471          
00472          new_hash = elf_link_hash_lookup (hash_table, ptr->new_name, FALSE, FALSE, TRUE);
00473 
00474          /* If we could not find the symbol then it is a new, undefined symbol.
00475             Symbian want this behaviour - ie they want to be able to rename the
00476             reference in a reloc from one undefined symbol to another, new and
00477             undefined symbol.  So we create that symbol here.  */
00478          if (new_hash == NULL)
00479            {
00480              asection *                     psec = bfd_und_section_ptr;
00481              Elf_Internal_Sym               new_sym;
00482              bfd_vma                        new_value = 0;
00483              bfd_boolean                    skip;
00484              bfd_boolean                    override;
00485              bfd_boolean                    type_change_ok;
00486              bfd_boolean                    size_change_ok;
00487 
00488              new_sym.st_value = 0;
00489              new_sym.st_size  = 0;
00490              new_sym.st_name  = -1;
00491              new_sym.st_info  = ELF_ST_INFO (STB_GLOBAL, STT_FUNC);
00492              new_sym.st_other = ELF_ST_VISIBILITY (STV_DEFAULT);
00493              new_sym.st_shndx = SHN_UNDEF;
00494 
00495              if (! _bfd_elf_merge_symbol (input_bfd, info,
00496                                       ptr->new_name, & new_sym,
00497                                       & psec, & new_value, NULL,
00498                                       & new_hash, & skip,
00499                                       & override, & type_change_ok,
00500                                       & size_change_ok))
00501               {
00502                 _bfd_error_handler (_("%B: Failed to add renamed symbol %s"),
00503                                   input_bfd, ptr->new_name);
00504                 continue;
00505               }
00506              /* XXX - should we check psec, skip, override etc ?  */
00507 
00508              new_hash->root.type = bfd_link_hash_undefined;
00509 
00510              /* Allow the symbol to become local if necessary.  */
00511              if (new_hash->dynindx == -1)
00512               new_hash->def_regular = 1;
00513 
00514              if (SYMBIAN_DEBUG)
00515               fprintf (stderr, "Created new symbol %s\n", ptr->new_name);
00516            }
00517 
00518          /* Convert the new_hash value into a index into the table of symbol hashes.  */
00519          for (h = sym_hashes; h < sym_hashes_end; h ++)
00520            {
00521              if (* h == new_hash)
00522               {
00523                 ptr->new_symndx = h - sym_hashes + num_local_syms;
00524                 if (SYMBIAN_DEBUG)
00525                   fprintf (stderr, "Converted new hash to index of %ld\n", ptr->new_symndx);
00526                 break;
00527               }
00528            }
00529          /* If the new symbol is not in the hash table then it must be
00530             because it is one of the newly created undefined symbols
00531             manufactured above.  So we extend the sym has table here to
00532             include this extra symbol.  */
00533          if (h == sym_hashes_end)
00534            {
00535              struct elf_link_hash_entry **  new_sym_hashes;
00536 
00537              /* This is not very efficient, but it works.  */
00538              ++ num_global_syms;
00539              new_sym_hashes = bfd_alloc (input_bfd, num_global_syms * sizeof * sym_hashes);
00540              if (new_sym_hashes == NULL)
00541               {
00542                 if (SYMBIAN_DEBUG)
00543                   fprintf (stderr, "Out of memory extending hash table\n");
00544                 continue;
00545               }
00546              memcpy (new_sym_hashes, sym_hashes, (num_global_syms - 1) * sizeof * sym_hashes);
00547              new_sym_hashes[num_global_syms - 1] = new_hash;
00548              elf_sym_hashes (input_bfd) = sym_hashes = new_sym_hashes;
00549              sym_hashes_end = sym_hashes + num_global_syms;
00550              symtab_hdr->sh_size  = (num_global_syms + num_local_syms) * sizeof (Elf32_External_Sym);
00551 
00552              ptr->new_symndx = num_global_syms - 1 + num_local_syms;
00553 
00554              if (SYMBIAN_DEBUG)
00555               fprintf (stderr, "Extended symbol hash table to insert new symbol as index %ld\n",
00556                       ptr->new_symndx);
00557            }
00558        }
00559 
00560       /* Walk the reloc list looking for references to renamed symbols.
00561         When we find one, we alter the index in the reloc to point to the new symbol.  */
00562       for (rel = relocs, relend = relocs + input_section->reloc_count;
00563           rel < relend;
00564           rel ++)
00565        {
00566          int                          r_type;
00567          unsigned long                r_symndx;
00568          struct elf_link_hash_entry * h;
00569       
00570          r_symndx = ELF32_R_SYM (rel->r_info);
00571          r_type = ELF32_R_TYPE (rel->r_info);
00572 
00573          /* Ignore unused relocs.  */
00574          if ((r_type >= (int) R_SH_GNU_VTINHERIT
00575               && r_type <= (int) R_SH_LABEL)
00576              || r_type == (int) R_SH_NONE
00577              || r_type < 0
00578              || r_type >= R_SH_max)
00579            continue;
00580 
00581          /* Ignore relocs against local symbols.  */
00582          if (r_symndx < num_local_syms)
00583            continue;
00584 
00585          BFD_ASSERT (r_symndx < (num_global_syms + num_local_syms));
00586          h = sym_hashes[r_symndx - num_local_syms];
00587          BFD_ASSERT (h != NULL);
00588 
00589          while (   h->root.type == bfd_link_hash_indirect
00590                || h->root.type == bfd_link_hash_warning)
00591            h = (struct elf_link_hash_entry *) h->root.u.i.link;
00592 
00593          /* If the symbol is defined there is no need to rename it.
00594             XXX - is this true ?  */
00595          if (   h->root.type == bfd_link_hash_defined
00596              || h->root.type == bfd_link_hash_defweak
00597              || h->root.type == bfd_link_hash_undefweak)
00598            continue;
00599 
00600          for (ptr = rename_list; ptr; ptr = ptr->next)
00601            if (h == ptr->current_hash)
00602              {
00603               BFD_ASSERT (ptr->new_symndx);
00604               if (SYMBIAN_DEBUG)
00605                 fprintf (stderr, "convert reloc %lx from using index %ld to using index %ld\n",
00606                         (long) rel->r_info, (long) ELF32_R_SYM (rel->r_info), ptr->new_symndx);
00607               rel->r_info = ELF32_R_INFO (ptr->new_symndx, r_type);
00608               break;
00609              }
00610        }
00611     }
00612   
00613   return sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
00614                               contents, relocs, local_syms, local_sections);
00615 }
00616 
00617 static bfd_boolean
00618 sh_symbian_check_directives (bfd *abfd, struct bfd_link_info *info)
00619 {
00620   return bfd_elf32_sh_symbian_process_directives (info, abfd);
00621 }
00622 
00623 #define TARGET_LITTLE_SYM   bfd_elf32_shl_symbian_vec
00624 #define TARGET_LITTLE_NAME      "elf32-shl-symbian"
00625 
00626 #undef  elf_backend_relocate_section
00627 #define elf_backend_relocate_section      sh_symbian_relocate_section
00628 #undef  elf_backend_check_directives
00629 #define elf_backend_check_directives    sh_symbian_check_directives
00630 
00631 #include "elf32-target.h"