* elflink.c (set_symbol_value): Add isymbuf and locsymcount
authorAlan Modra <amodra@gmail.com>
Wed, 26 Sep 2007 12:29:41 +0000 (12:29 +0000)
committerAlan Modra <amodra@gmail.com>
Wed, 26 Sep 2007 12:29:41 +0000 (12:29 +0000)
params.  Change symidx to a size_t.  Don't access past end
of symbol buffer.
(resolve_symbol): Add isymbuf param and use instead of
finfo->internal_syms.
(eval_symbol, evaluate_complex_relocation_symbols): Likewise.
(elf_link_input_bfd): Don't read symbols specially for
evaluate_complex_relocation_symbols.

bfd/ChangeLog
bfd/elflink.c

index f93f756..afbd748 100644 (file)
@@ -1,3 +1,14 @@
+2007-09-26  Alan Modra  <amodra@bigpond.net.au>
+
+       * elflink.c (set_symbol_value): Add isymbuf and locsymcount
+       params.  Change symidx to a size_t.  Don't access past end
+       of symbol buffer.
+       (resolve_symbol): Add isymbuf param and use instead of
+       finfo->internal_syms.
+       (eval_symbol, evaluate_complex_relocation_symbols): Likewise.
+       (elf_link_input_bfd): Don't read symbols specially for
+       evaluate_complex_relocation_symbols.
+
 2007-09-26  Tristan Gingold  <gingold@adacore.com>
 
        * som.c (som_get_reloc_upper_bound): If there are no relocs return
index 8e17f89..ce59c3a 100644 (file)
@@ -7230,38 +7230,43 @@ struct elf_outext_info
 
 static void
 set_symbol_value (bfd *                         bfd_with_globals,
-                 struct elf_final_link_info *  finfo,    
-                 int                           symidx,
+                 Elf_Internal_Sym *            isymbuf,
+                 size_t                        locsymcount,
+                 size_t                        symidx,
                  bfd_vma                       val)
 {
-  bfd_boolean                    is_local;
-  Elf_Internal_Sym *             sym;
-  struct elf_link_hash_entry **  sym_hashes;
-  struct elf_link_hash_entry *   h;
+  struct elf_link_hash_entry **sym_hashes;
+  struct elf_link_hash_entry *h;
+  size_t extsymoff = locsymcount;
 
-  sym_hashes = elf_sym_hashes (bfd_with_globals);
-  sym = finfo->internal_syms + symidx;  
-  is_local = ELF_ST_BIND(sym->st_info) == STB_LOCAL;
-  
-  if (is_local)
-    {
-      /* It is a local symbol: move it to the
-        "absolute" section and give it a value.  */
-      sym->st_shndx = SHN_ABS;
-      sym->st_value = val;
-    }
-  else 
+  if (symidx < locsymcount)
     {
-      /* It is a global symbol: set its link type
-        to "defined" and give it a value.  */
-      h = sym_hashes [symidx];   
-      while (h->root.type == bfd_link_hash_indirect
-            || h->root.type == bfd_link_hash_warning)
-       h = (struct elf_link_hash_entry *) h->root.u.i.link;
-      h->root.type = bfd_link_hash_defined;
-      h->root.u.def.value = val;
-      h->root.u.def.section = bfd_abs_section_ptr;
+      Elf_Internal_Sym *sym;
+
+      sym = isymbuf + symidx;
+      if (ELF_ST_BIND (sym->st_info) == STB_LOCAL)
+       {
+         /* It is a local symbol: move it to the
+            "absolute" section and give it a value.  */
+         sym->st_shndx = SHN_ABS;
+         sym->st_value = val;
+         return;
+       }
+      BFD_ASSERT (elf_bad_symtab (bfd_with_globals));
+      extsymoff = 0;
     }
+
+  /* It is a global symbol: set its link type
+     to "defined" and give it a value.  */
+
+  sym_hashes = elf_sym_hashes (bfd_with_globals);
+  h = sym_hashes [symidx - extsymoff];
+  while (h->root.type == bfd_link_hash_indirect
+        || h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+  h->root.type = bfd_link_hash_defined;
+  h->root.u.def.value = val;
+  h->root.u.def.section = bfd_abs_section_ptr;
 }
 
 static bfd_boolean 
@@ -7269,6 +7274,7 @@ resolve_symbol (const char *                  name,
                bfd *                         input_bfd,
                struct elf_final_link_info *  finfo,
                bfd_vma *                     result,
+               Elf_Internal_Sym *            isymbuf,
                size_t                        locsymcount)
 {
   Elf_Internal_Sym *            sym;
@@ -7282,7 +7288,7 @@ resolve_symbol (const char *                  name,
 
   for (i = 0; i < locsymcount; ++ i)
     {
-      sym = finfo->internal_syms + i;
+      sym = isymbuf + i;
       sec = finfo->sections [i];
 
       if (ELF_ST_BIND (sym->st_info) != STB_LOCAL)
@@ -7402,6 +7408,7 @@ eval_symbol (bfd_vma *                     result,
             struct elf_final_link_info *  finfo,
             bfd_vma                       addr,
             bfd_vma                       section_offset,
+            Elf_Internal_Sym *            isymbuf,
             size_t                        locsymcount,
             int                           signed_p)
 {
@@ -7459,8 +7466,9 @@ eval_symbol (bfd_vma *                     result,
 
       if (symbol_is_section) 
        {
-         if ((resolve_section (symbuf, finfo->output_bfd->sections, result) != TRUE)
-             && (resolve_symbol (symbuf, input_bfd, finfo, result, locsymcount) != TRUE))
+         if (!resolve_section (symbuf, finfo->output_bfd->sections, result)
+             && !resolve_symbol (symbuf, input_bfd, finfo, result,
+                                 isymbuf, locsymcount))
            {
              undefined_reference ("section", symbuf);
              return FALSE;
@@ -7468,9 +7476,10 @@ eval_symbol (bfd_vma *                     result,
        } 
       else 
        {
-         if ((resolve_symbol (symbuf, input_bfd, finfo, result, locsymcount) != TRUE)
-             && (resolve_section (symbuf, finfo->output_bfd->sections,
-                                  result) != TRUE))
+         if (!resolve_symbol (symbuf, input_bfd, finfo, result,
+                              isymbuf, locsymcount)
+             && !resolve_section (symbuf, finfo->output_bfd->sections,
+                                  result))
            {
              undefined_reference ("symbol", symbuf);
              return FALSE;
@@ -7487,9 +7496,9 @@ eval_symbol (bfd_vma *                     result,
       sym += strlen (#op);                                     \
       if (* sym == ':')                                                \
         ++ sym;                                                        \
-      if (eval_symbol (& a, sym, & sym, input_bfd, finfo, addr, \
-                       section_offset, locsymcount, signed_p)   \
-                                                    != TRUE)   \
+      if (!eval_symbol (&a, sym, &sym, input_bfd, finfo, addr, \
+                       section_offset, isymbuf, locsymcount,   \
+                       signed_p))                              \
         return FALSE;                                          \
       if (signed_p)                                             \
         * result = op ((signed)a);                             \
@@ -7505,14 +7514,14 @@ eval_symbol (bfd_vma *                     result,
       sym += strlen (#op);                                     \
       if (* sym == ':')                                                \
         ++ sym;                                                        \
-      if (eval_symbol (& a, sym, & sym, input_bfd, finfo, addr, \
-                       section_offset, locsymcount, signed_p)   \
-                                                     != TRUE)  \
+      if (!eval_symbol (&a, sym, &sym, input_bfd, finfo, addr, \
+                       section_offset, isymbuf, locsymcount,   \
+                       signed_p))                              \
         return FALSE;                                          \
       ++ sym;                                                  \
-      if (eval_symbol (& b, sym, & sym, input_bfd, finfo, addr, \
-                       section_offset, locsymcount, signed_p)   \
-                                                     != TRUE)  \
+      if (!eval_symbol (&b, sym, &sym, input_bfd, finfo, addr, \
+                       section_offset, isymbuf, locsymcount,   \
+                       signed_p))                              \
         return FALSE;                                          \
       if (signed_p)                                             \
         * result = ((signed) a) op ((signed) b);               \
@@ -7555,8 +7564,9 @@ eval_symbol (bfd_vma *                     result,
 /* Entry point to evaluator, called from elf_link_input_bfd.  */
 
 static bfd_boolean
-evaluate_complex_relocation_symbols (bfd * input_bfd,
-                                    struct elf_final_link_info * finfo,
+evaluate_complex_relocation_symbols (bfd *input_bfd,
+                                    struct elf_final_link_info *finfo,
+                                    Elf_Internal_Sym *isymbuf,
                                     size_t locsymcount)
 {
   const struct elf_backend_data * bed;
@@ -7626,7 +7636,7 @@ evaluate_complex_relocation_symbols (bfd * input_bfd,
          if (index < locsymcount)
            {
              /* The symbol is local.  */
-             sym = finfo->internal_syms + index;
+             sym = isymbuf + index;
 
              /* We're only processing STT_RELC or STT_SRELC type symbols.  */
              if ((ELF_ST_TYPE (sym->st_info) != STT_RELC) &&
@@ -7668,10 +7678,10 @@ evaluate_complex_relocation_symbols (bfd * input_bfd,
          printf (" Evaluating '%s' ...\n ", sym_name);
 #endif
          if (eval_symbol (& result, sym_name, & sym_name, input_bfd, 
-                          finfo, addr, section_offset, locsymcount,
+                          finfo, addr, section_offset, isymbuf, locsymcount,
                           signed_p))
            /* Symbol evaluated OK.  Update to absolute value.  */
-           set_symbol_value (input_bfd, finfo, index, result);
+           set_symbol_value (input_bfd, isymbuf, locsymcount, index, result);
 
          else
            result = FALSE;
@@ -9066,15 +9076,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
       if (isymbuf == NULL)
        return FALSE;
     }
-  /* evaluate_complex_relocation_symbols looks for symbols in
-     finfo->internal_syms.  */
-  else if (isymbuf != NULL && locsymcount != 0)
-    {
-      bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0,
-                           finfo->internal_syms,
-                           finfo->external_syms,
-                           finfo->locsym_shndx);
-    }
 
   /* Find local symbol sections and adjust values of symbols in
      SEC_MERGE sections.  Write out those local symbols we know are
@@ -9212,7 +9213,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
        return FALSE;
     }
 
-  if (! evaluate_complex_relocation_symbols (input_bfd, finfo, locsymcount))
+  if (! evaluate_complex_relocation_symbols (input_bfd, finfo, isymbuf,
+                                            locsymcount))
     return FALSE;
 
   /* Relocate the contents of each section.  */