Jakub Jelinek <jj@ultra.linux.cz>
authorRichard Henderson <rth@redhat.com>
Fri, 30 Jul 1999 21:34:44 +0000 (21:34 +0000)
committerRichard Henderson <rth@redhat.com>
Fri, 30 Jul 1999 21:34:44 +0000 (21:34 +0000)
        * elf-bfd.h (struct elf_backend_data): Add
        print_symbol_all and output_arch_syms backend methods.
        * elfxx-target.h: Likewise.
        * elf64-sparc.c (sparc64_elf_bfd_link_hash_table_create,
        sparc64_elf_add_symbol_hook, sparc64_elf_output_arch_syms,
        sparc64_elf_get_symbol_type, sparc64_elf_symbol_processing): New
        functions.
        (sparc64_elf_size_dynamic_sections): Leave space for STT_REGISTER
        symbols in .dynsym, add their names into .dynstr. Put those symbols
        into dynlocal.
        (sparc64_elf_finish_dynamic_sections): Fix up DT_SPARC_REGISTER
        pointers to STT_REGISTER symbols in dynsym section.
        (sparc64_elf_print_symbol_all): New function.
        * elf.c (bfd_elf_print_symbol): Allow special backend symbol
        printing using the print_symbol_all hook.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf.c
bfd/elf64-sparc.c
bfd/elflink.h
bfd/elfxx-target.h

index 5ca7ca4020911e4ba4105ea8d689c69a1c0d2f8f..a6ce27659d9e01eda4105fb01ae53487653d6bba 100644 (file)
@@ -1,3 +1,21 @@
+1999-07-30  Jakub Jelinek  <jj@ultra.linux.cz>
+
+       * elf-bfd.h (struct elf_backend_data): Add
+       print_symbol_all and output_arch_syms backend methods.
+       * elfxx-target.h: Likewise.
+       * elf64-sparc.c (sparc64_elf_bfd_link_hash_table_create,
+       sparc64_elf_add_symbol_hook, sparc64_elf_output_arch_syms,
+       sparc64_elf_get_symbol_type, sparc64_elf_symbol_processing): New
+       functions.
+       (sparc64_elf_size_dynamic_sections): Leave space for STT_REGISTER
+       symbols in .dynsym, add their names into .dynstr. Put those symbols
+       into dynlocal.
+       (sparc64_elf_finish_dynamic_sections): Fix up DT_SPARC_REGISTER
+       pointers to STT_REGISTER symbols in dynsym section.
+       (sparc64_elf_print_symbol_all): New function.
+       * elf.c (bfd_elf_print_symbol): Allow special backend symbol
+       printing using the print_symbol_all hook.
+
 1999-07-30  Catherine Moore  <clm@cygnus.com>
 
        * elf32-arm.h (elf32_arm_check_relocs):  Use r_offset for
index 577823b8257f0abbc195b43306365328de7dac29..3fa25136fd2d32aa992c666ec3ded9c0cc71767e 100644 (file)
@@ -581,6 +581,21 @@ struct elf_backend_data
   void (*elf_backend_post_process_headers)
     PARAMS ((bfd *, struct bfd_link_info *));
 
+  /* This function, if defined, prints a symbol to file and returns the
+     name of the symbol to be printed.  It should return NULL to fall
+     back to default symbol printing.  */
+  const char *(*elf_backend_print_symbol_all)
+    PARAMS ((bfd *, PTR, asymbol *));
+
+  /* This function, if defined, is called after all local symbols and
+     global symbols converted to locals are emited into the symtab
+     section.  It allows the backend to emit special global symbols
+     not handled in the hash table.  */
+  boolean (*elf_backend_output_arch_syms)
+    PARAMS ((bfd *, struct bfd_link_info *, PTR,
+           boolean (*) PARAMS ((PTR, const char *,
+             Elf_Internal_Sym *, asection *))));
+
   /* The swapping table to use when dealing with ECOFF information.
      Used for the MIPS ELF .mdebug section.  */
   const struct ecoff_debug_swap *elf_backend_ecoff_debug_swap;
index 9291b9887f03fc75569be4bb2e493711a0835224..997408ce16e5ad12bec7bf3e2f9fb18aee5d9e02 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -758,8 +758,21 @@ bfd_elf_print_symbol (abfd, filep, symbol, how)
     case bfd_print_symbol_all:
       {
        CONST char *section_name;
+       CONST char *name = NULL;
+       struct elf_backend_data *bed;
+       
        section_name = symbol->section ? symbol->section->name : "(*none*)";
-       bfd_print_symbol_vandf ((PTR) file, symbol);
+
+       bed = get_elf_backend_data (abfd);
+       if (bed->elf_backend_print_symbol_all)
+           name = (*bed->elf_backend_print_symbol_all) (abfd, filep, symbol);
+
+       if (name == NULL)
+         {
+           name = symbol->name;  
+           bfd_print_symbol_vandf ((PTR) file, symbol);
+         }
+
        fprintf (file, " %s\t", section_name);
        /* Print the "other" value for a symbol.  For common symbols,
           we've already printed the size; now print the alignment.
@@ -827,7 +840,7 @@ bfd_elf_print_symbol (abfd, filep, symbol, how)
                   ((unsigned int)
                    ((elf_symbol_type *) symbol)->internal_elf_sym.st_other));
 
-       fprintf (file, " %s", symbol->name);
+       fprintf (file, " %s", name);
       }
       break;
     }
index 255713e3d70a2085d9fdd1ddcdf1e7906d75c672..107f37140297cca70a220641ed276e88b76dc767 100644 (file)
@@ -32,6 +32,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value.  */
 #define MINUS_ONE (~ (bfd_vma) 0)
 
+static struct bfd_link_hash_table * sparc64_elf_bfd_link_hash_table_create
+  PARAMS((bfd *));
 static reloc_howto_type *sparc64_elf_reloc_type_lookup
   PARAMS ((bfd *, bfd_reloc_code_real_type));
 static void sparc64_elf_info_to_howto
@@ -51,6 +53,13 @@ static boolean sparc64_elf_adjust_dynamic_symbol
   PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *));
 static boolean sparc64_elf_size_dynamic_sections
   PARAMS((bfd *, struct bfd_link_info *));
+static int sparc64_elf_get_symbol_type
+  PARAMS (( Elf_Internal_Sym *, int));
+static boolean sparc64_elf_add_symbol_hook
+  PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
+        const char **, flagword *, asection **, bfd_vma *));
+static void sparc64_elf_symbol_processing
+  PARAMS ((bfd *, asymbol *));
 
 static boolean sparc64_elf_merge_private_bfd_data
   PARAMS ((bfd *, bfd *));
@@ -595,6 +604,52 @@ sparc64_elf_write_relocs (abfd, sec, data)
       bfd_elf64_swap_reloca_out (abfd, &dst_rela, src_rela);
     }
 }
+\f
+/* Sparc64 ELF linker hash table.  */
+
+struct sparc64_elf_app_reg
+{
+  unsigned char bind;
+  unsigned short shndx;
+  bfd *abfd;
+  char *name;
+};
+
+struct sparc64_elf_link_hash_table
+{
+  struct elf_link_hash_table root;
+
+  struct sparc64_elf_app_reg app_regs [4];
+};
+
+/* Get the Sparc64 ELF linker hash table from a link_info structure.  */
+
+#define sparc64_elf_hash_table(p) \
+  ((struct sparc64_elf_link_hash_table *) ((p)->hash))
+  
+/* Create a Sparc64 ELF linker hash table.  */
+
+static struct bfd_link_hash_table *
+sparc64_elf_bfd_link_hash_table_create (abfd)
+     bfd *abfd;
+{
+  struct sparc64_elf_link_hash_table *ret;
+
+  ret = ((struct sparc64_elf_link_hash_table *)
+        bfd_zalloc (abfd, sizeof (struct sparc64_elf_link_hash_table)));
+  if (ret == (struct sparc64_elf_link_hash_table *) NULL)
+    return NULL;
+
+  if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
+                                      _bfd_elf_link_hash_newfunc))
+    {
+      bfd_release (abfd, ret);
+      return NULL;
+    }
+
+  return &ret->root.root;
+}
+
 \f
 /* Utility for performing the standard initial work of an instruction
    relocation.
@@ -1196,6 +1251,221 @@ sparc64_elf_check_relocs (abfd, info, sec, relocs)
   return true;
 }
 
+/* Hook called by the linker routine which adds symbols from an object
+   file.  We use it for STT_REGISTER symbols.  */
+
+static boolean
+sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
+     bfd *abfd;
+     struct bfd_link_info *info;
+     const Elf_Internal_Sym *sym;
+     const char **namep;
+     flagword *flagsp;
+     asection **secp;
+     bfd_vma *valp;
+{
+  static char *stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" };
+
+  if (ELF_ST_TYPE (sym->st_info) == STT_REGISTER)
+    {
+      int reg;
+      struct sparc64_elf_app_reg *p;
+      
+      reg = (int)sym->st_value;
+      switch (reg & ~1)
+       {
+       case 2: reg -= 2; break;
+       case 6: reg -= 4; break;
+       default:
+          (*_bfd_error_handler)
+            (_("%s: Only registers %%g[2367] can be declared using STT_REGISTER"),
+             bfd_get_filename (abfd));
+         return false;
+       }
+
+      if (info->hash->creator != abfd->xvec
+         || (abfd->flags & DYNAMIC) != 0)
+        {
+         /* STT_REGISTER only works when linking an elf64_sparc object.
+            If STT_REGISTER comes from a dynamic object, don't put it into
+            the output bfd.  The dynamic linker will recheck it.  */
+         *namep = NULL;
+         return true;
+        }
+
+      p = sparc64_elf_hash_table(info)->app_regs + reg;
+
+      if (p->name != NULL && strcmp (p->name, *namep))
+       {
+          (*_bfd_error_handler)
+            (_("Register %%g%d used incompatibly: "
+               "previously declared in %s to %s, in %s redefined to %s"),
+             (int)sym->st_value,
+             bfd_get_filename (p->abfd), *p->name ? p->name : "#scratch",
+             bfd_get_filename (abfd), **namep ? *namep : "#scratch");
+         return false;
+       }
+
+      if (p->name == NULL)
+       {
+         if (**namep)
+           {
+             struct elf_link_hash_entry *h;
+             
+             h = (struct elf_link_hash_entry *)
+               bfd_link_hash_lookup (info->hash, *namep, false, false, false);
+
+             if (h != NULL)
+               {
+                 unsigned char type = h->type;
+
+                 if (type > STT_FUNC) type = 0;
+                 (*_bfd_error_handler)
+                   (_("Symbol `%s' has differing types: "
+                      "previously %s, REGISTER in %s"),
+                    *namep, stt_types [type], bfd_get_filename (abfd));
+                 return false;
+               }
+
+             p->name = bfd_hash_allocate (&info->hash->table,
+                                          strlen (*namep) + 1);
+             if (!p->name)
+               return false;
+
+             strcpy (p->name, *namep);
+           }
+         else
+           p->name = "";
+         p->bind = ELF_ST_BIND (sym->st_info);
+         p->abfd = abfd;
+         p->shndx = sym->st_shndx;
+       }
+      else
+       {
+         if (p->bind == STB_WEAK
+             && ELF_ST_BIND (sym->st_info) == STB_GLOBAL)
+           {
+             p->bind = STB_GLOBAL;
+             p->abfd = abfd;
+           }
+       }
+      *namep = NULL;
+      return true;
+    }
+  else if (! *namep || ! **namep)
+    return true;
+  else
+    {
+      int i;
+      struct sparc64_elf_app_reg *p;
+
+      p = sparc64_elf_hash_table(info)->app_regs;
+      for (i = 0; i < 4; i++, p++)
+       if (p->name != NULL && ! strcmp (p->name, *namep))
+         {
+           unsigned char type = ELF_ST_TYPE (sym->st_info);
+
+           if (type > STT_FUNC) type = 0;
+           (*_bfd_error_handler)
+             (_("Symbol `%s' has differing types: "
+                "REGISTER in %s, %s in %s"),
+              *namep, bfd_get_filename (p->abfd), stt_types [type],
+              bfd_get_filename (abfd));
+           return false;
+         }
+    }
+  return true;
+}
+
+/* This function takes care of emiting STT_REGISTER symbols
+   which we cannot easily keep in the symbol hash table.  */
+
+static boolean
+sparc64_elf_output_arch_syms (output_bfd, info, finfo, func)
+     bfd *output_bfd;
+     struct bfd_link_info *info;
+     PTR finfo;
+     boolean (*func) PARAMS ((PTR, const char *,
+                             Elf_Internal_Sym *, asection *));
+{
+  int reg;
+  struct sparc64_elf_app_reg *app_regs =
+    sparc64_elf_hash_table(info)->app_regs;
+  Elf_Internal_Sym sym;
+
+  /* We arranged in size_dynamic_sections to put the STT_REGISTER entries
+     at the end of the dynlocal list, so they came at the end of the local
+     symbols in the symtab.  Except that they aren't STB_LOCAL, so we need
+     to back up symtab->sh_info.  */
+  if (elf_hash_table (info)->dynlocal)
+    {
+      struct elf_link_local_dynamic_entry *e;
+
+      for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
+       if (e->input_indx == -1)
+         break;
+      if (e)
+       {
+         elf_section_data (dynsymsec->output_section)->this_hdr.sh_info
+           = e->dynindx;
+       }
+    }
+
+  if (info->strip == strip_all)
+    return true;
+
+  for (reg = 0; reg < 4; reg++)
+    if (app_regs [reg].name != NULL)
+      {
+       if (info->strip == strip_some
+           && bfd_hash_lookup (info->keep_hash,
+                               app_regs [reg].name,
+                               false, false) == NULL)
+         continue;
+
+       sym.st_value = reg < 2 ? reg + 2 : reg + 4;
+       sym.st_size = 0;
+       sym.st_other = 0;
+       sym.st_info = ELF_ST_INFO (app_regs [reg].bind, STT_REGISTER);
+       sym.st_shndx = app_regs [reg].shndx;
+       if (! (*func) (finfo, app_regs [reg].name, &sym,
+                      sym.st_shndx == SHN_ABS
+                        ? bfd_abs_section_ptr : bfd_und_section_ptr))
+         return false;
+      }
+
+  return true;
+}
+
+static int
+sparc64_elf_get_symbol_type (elf_sym, type)
+     Elf_Internal_Sym * elf_sym;
+     int type;
+{
+  if (ELF_ST_TYPE (elf_sym->st_info) == STT_REGISTER)
+    return STT_REGISTER;
+  else
+    return type;
+}
+
+/* A STB_GLOBAL,STT_REGISTER symbol should be BSF_GLOBAL
+   even in SHN_UNDEF section.  */
+
+static void
+sparc64_elf_symbol_processing (abfd, asym)
+     bfd *abfd;
+     asymbol *asym;
+{
+  elf_symbol_type *elfsym;
+
+  elfsym = (elf_symbol_type *) asym;
+  if (elfsym->internal_elf_sym.st_info
+      == ELF_ST_INFO (STB_GLOBAL, STT_REGISTER))
+    {
+      asym->flags |= BSF_GLOBAL;
+    }
+}
+
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
    dynamic object, but we're not including those sections.  We have to
@@ -1495,6 +1765,11 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
         must add the entries now so that we get the correct size for
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
+      int reg;
+      struct sparc64_elf_app_reg * app_regs;
+      struct bfd_strtab_hash *dynstr;
+      struct elf_link_hash_table *eht = elf_hash_table (info);
+
       if (! info->shared)
        {
          if (! bfd_elf64_add_dynamic_entry (info, DT_DEBUG, 0))
@@ -1521,6 +1796,53 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
          if (! bfd_elf64_add_dynamic_entry (info, DT_TEXTREL, 0))
            return false;
        }
+
+      /* Add dynamic STT_REGISTER symbols and corresponding DT_SPARC_REGISTER
+        entries if needed.  */
+      app_regs = sparc64_elf_hash_table (info)->app_regs;
+      dynstr = eht->dynstr;
+
+      for (reg = 0; reg < 4; reg++)
+       if (app_regs [reg].name != NULL)
+         {
+           struct elf_link_local_dynamic_entry *entry, *e;
+             
+           if (! bfd_elf64_add_dynamic_entry (info, DT_SPARC_REGISTER, 0))
+             return false;
+
+           entry = (struct elf_link_local_dynamic_entry *)
+             bfd_hash_allocate (&info->hash->table, sizeof (*entry));
+           if (entry == NULL)
+             return false;
+
+           /* We cheat here a little bit: the symbol will not be local, so we
+              put it at the end of the dynlocal linked list.  We will fix it
+              later on, as we have to fix other fields anyway.  */
+           entry->isym.st_value = reg < 2 ? reg + 2 : reg + 4;
+           entry->isym.st_size = 0;
+           if (*app_regs [reg].name != '\0')
+             entry->isym.st_name
+               = _bfd_stringtab_add (dynstr, app_regs[reg].name, true, false);
+           else
+             entry->isym.st_name = 0;
+           entry->isym.st_other = 0;
+           entry->isym.st_info = ELF_ST_INFO (app_regs [reg].bind,
+                                              STT_REGISTER);
+           entry->isym.st_shndx = app_regs [reg].shndx;
+           entry->next = NULL;
+           entry->input_bfd = output_bfd;
+           entry->input_indx = -1;
+
+           if (eht->dynlocal == NULL)
+             eht->dynlocal = entry;
+           else
+             {
+               for (e = eht->dynlocal; e->next; e = e->next)
+                 ;
+               e->next = entry;
+             }
+           eht->dynsymcount++;
+         }
     }
 
   return true;
@@ -2346,6 +2668,7 @@ sparc64_elf_finish_dynamic_sections (output_bfd, info)
      struct bfd_link_info *info;
 {
   bfd *dynobj;
+  int stt_regidx = -1;
   asection *sdyn;
   asection *sgot;
 
@@ -2376,6 +2699,17 @@ sparc64_elf_finish_dynamic_sections (output_bfd, info)
            case DT_PLTGOT:   name = ".plt"; size = false; break;
            case DT_PLTRELSZ: name = ".rela.plt"; size = true; break;
            case DT_JMPREL:   name = ".rela.plt"; size = false; break;
+           case DT_SPARC_REGISTER:
+             if (stt_regidx == -1)
+               {
+                 stt_regidx =
+                   _bfd_elf_link_lookup_local_dynindx (info, output_bfd, -1);
+                 if (stt_regidx == -1)
+                   return false;
+               }
+             dyn.d_un.d_val = stt_regidx++;
+             bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
+             /* fallthrough */
            default:          name = NULL; size = false; break;
            }
 
@@ -2505,7 +2839,34 @@ sparc64_elf_merge_private_bfd_data (ibfd, obfd)
     }
   return true;
 }
+\f
+/* Print a STT_REGISTER symbol to file FILE.  */
 
+static const char *
+sparc64_elf_print_symbol_all (abfd, filep, symbol)
+     bfd *abfd;
+     PTR filep;
+     asymbol *symbol;
+{
+  FILE *file = (FILE *) filep;
+  int reg, type;
+  
+  if (ELF_ST_TYPE (((elf_symbol_type *) symbol)->internal_elf_sym.st_info)
+      != STT_REGISTER)
+    return NULL;
+
+  reg = ((elf_symbol_type *) symbol)->internal_elf_sym.st_value;
+  type = symbol->flags;
+  fprintf (file, "REG_%c%c%11s%c%c    R", "GOLI" [reg / 8], '0' + (reg & 7), "",
+                ((type & BSF_LOCAL)
+                 ? (type & BSF_GLOBAL) ? '!' : 'l'
+                 : (type & BSF_GLOBAL) ? 'g' : ' '),
+                (type & BSF_WEAK) ? 'w' : ' ');
+  if (symbol->name == NULL || symbol->name [0] == '\0')
+    return "#scratch";
+  else
+    return symbol->name;
+}
 \f
 /* Set the right machine number for a SPARC64 ELF file.  */
 
@@ -2570,6 +2931,9 @@ const struct elf_size_info sparc64_elf_size_info =
 /* This is the value that we used before the ABI was released.  */
 #define ELF_MACHINE_ALT1 EM_OLD_SPARCV9
 
+#define bfd_elf64_bfd_link_hash_table_create \
+  sparc64_elf_bfd_link_hash_table_create
+  
 #define elf_info_to_howto \
   sparc64_elf_info_to_howto
 #define bfd_elf64_get_reloc_upper_bound \
@@ -2583,6 +2947,12 @@ const struct elf_size_info sparc64_elf_size_info =
 
 #define elf_backend_create_dynamic_sections \
   _bfd_elf_create_dynamic_sections
+#define elf_backend_add_symbol_hook \
+  sparc64_elf_add_symbol_hook
+#define elf_backend_get_symbol_type \
+  sparc64_elf_get_symbol_type
+#define elf_backend_symbol_processing \
+  sparc64_elf_symbol_processing
 #define elf_backend_check_relocs \
   sparc64_elf_check_relocs
 #define elf_backend_adjust_dynamic_symbol \
@@ -2595,6 +2965,10 @@ const struct elf_size_info sparc64_elf_size_info =
   sparc64_elf_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_sections \
   sparc64_elf_finish_dynamic_sections
+#define elf_backend_print_symbol_all \
+  sparc64_elf_print_symbol_all
+#define elf_backend_output_arch_syms \
+  sparc64_elf_output_arch_syms
 
 #define bfd_elf64_bfd_merge_private_bfd_data \
   sparc64_elf_merge_private_bfd_data
index 6fb9bbae8a184bd3c748c8bddf10d296ef94cb13..cfb49098827c4b8d4b6727feeb45804b68b87397 100644 (file)
@@ -2116,6 +2116,10 @@ elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx)
   entry->input_indx = input_indx;
   eht->dynsymcount++;
 
+  /* Whatever binding the symbol had before, it's now local.  */
+  entry->isym.st_info
+    = ELF_ST_INFO (STB_LOCAL, ELF_ST_TYPE (entry->isym.st_info));
+
   /* The dynindx will be set at the end of size_dynamic_sections.  */
 
   return true;
@@ -4253,16 +4257,22 @@ elf_bfd_final_link (abfd, info)
                  the original st_name with the dynstr_index.  */
              sym.st_name = e->isym.st_name;
 
-             /* Whatever binding the symbol had before, it's now local.  */
-             sym.st_info = ELF_ST_INFO (STB_LOCAL,
-                                        ELF_ST_TYPE (e->isym.st_info));
-
-             s = bfd_section_from_elf_index (e->input_bfd, e->isym.st_shndx);
-
-             sym.st_shndx = elf_section_data (s->output_section)->this_idx;
-             sym.st_value = (s->output_section->vma
-                             + s->output_offset
-                             + e->isym.st_value);
+             if (e->isym.st_shndx == 0 || e->isym.st_shndx >= SHN_LORESERVE)
+               {
+                 sym.st_shndx = e->isym.st_shndx;
+                 sym.st_value = e->isym.st_value;
+               }
+             else
+               {
+                 s = bfd_section_from_elf_index (e->input_bfd,
+                                                 e->isym.st_shndx);
+
+                 sym.st_shndx =
+                   elf_section_data (s->output_section)->this_idx;
+                 sym.st_value = (s->output_section->vma
+                                 + s->output_offset
+                                 + e->isym.st_value);
+               }
 
              if (last_local < e->dynindx)
                last_local = e->dynindx;
@@ -4272,7 +4282,7 @@ elf_bfd_final_link (abfd, info)
        }
 
       elf_section_data (finfo.dynsym_sec->output_section)
-       ->this_hdr.sh_info = last_local;
+       ->this_hdr.sh_info = last_local + 1;
     }
 
   /* We get the global symbols from the hash table.  */
@@ -4284,6 +4294,18 @@ elf_bfd_final_link (abfd, info)
   if (eoinfo.failed)
     return false;
 
+  /* If backend needs to output some symbols not present in the hash
+     table, do it now.  */
+  if (bed->elf_backend_output_arch_syms)
+    {
+      if (! (*bed->elf_backend_output_arch_syms)
+             (abfd, info, (PTR) &finfo,
+              (boolean (*) PARAMS ((PTR, const char *,
+                           Elf_Internal_Sym *, asection *)))
+              elf_link_output_sym))
+       return false;
+    }      
+
   /* Flush all symbols to the file.  */
   if (! elf_link_flush_output_syms (&finfo))
     return false;
index d40a8706808e2cd3c71a05aae399288e7e73e0b5..3a787a268d3e3d67a7909257756a635550382b2e 100644 (file)
@@ -297,6 +297,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #ifndef elf_backend_post_process_headers
 #define elf_backend_post_process_headers       NULL
 #endif
+#ifndef elf_backend_print_symbol_all
+#define elf_backend_print_symbol_all           NULL
+#endif
+#ifndef elf_backend_output_arch_syms
+#define elf_backend_output_arch_syms           NULL
+#endif
 
 /* Previously, backends could only use SHT_REL or SHT_RELA relocation
    sections, but not both.  They defined USE_REL to indicate SHT_REL
@@ -369,6 +375,8 @@ static CONST struct elf_backend_data elfNN_bed =
   elf_backend_gc_mark_hook,
   elf_backend_gc_sweep_hook,
   elf_backend_post_process_headers,
+  elf_backend_print_symbol_all,
+  elf_backend_output_arch_syms,
   elf_backend_ecoff_debug_swap,
   ELF_MACHINE_ALT1,
   ELF_MACHINE_ALT2,