-/* 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,
- size_t locsymcount)
-{
- const struct elf_backend_data * bed;
- Elf_Internal_Shdr * symtab_hdr;
- struct elf_link_hash_entry ** sym_hashes;
- asection * reloc_sec;
- bfd_boolean result = TRUE;
-
- /* For each section, we're going to check and see if it has any
- complex relocations, and we're going to evaluate any of them
- we can. */
-
- if (finfo->info->relocatable)
- return TRUE;
-
- symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (input_bfd);
- bed = get_elf_backend_data (input_bfd);
-
- for (reloc_sec = input_bfd->sections; reloc_sec; reloc_sec = reloc_sec->next)
- {
- Elf_Internal_Rela * internal_relocs;
- unsigned long i;
-
- /* This section was omitted from the link. */
- if (! reloc_sec->linker_mark)
- continue;
-
- /* Only process sections containing relocs. */
- if ((reloc_sec->flags & SEC_RELOC) == 0)
- continue;
-
- if (reloc_sec->reloc_count == 0)
- continue;
-
- /* Read in the relocs for this section. */
- internal_relocs
- = _bfd_elf_link_read_relocs (input_bfd, reloc_sec, NULL,
- (Elf_Internal_Rela *) NULL,
- FALSE);
- if (internal_relocs == NULL)
- continue;
-
- for (i = reloc_sec->reloc_count; i--;)
- {
- Elf_Internal_Rela * rel;
- char * sym_name;
- bfd_vma index;
- Elf_Internal_Sym * sym;
- bfd_vma result;
- bfd_vma section_offset;
- bfd_vma addr;
- int signed_p = 0;
-
- rel = internal_relocs + i;
- section_offset = reloc_sec->output_section->vma
- + reloc_sec->output_offset;
- addr = rel->r_offset;
-
- index = ELF32_R_SYM (rel->r_info);
- if (bed->s->arch_size == 64)
- index >>= 24;
-
- if (index == STN_UNDEF)
- continue;
-
- if (index < locsymcount)
- {
- /* The symbol is local. */
- sym = finfo->internal_syms + index;
-
- /* We're only processing STT_RELC or STT_SRELC type symbols. */
- if ((ELF_ST_TYPE (sym->st_info) != STT_RELC) &&
- (ELF_ST_TYPE (sym->st_info) != STT_SRELC))
- continue;
-
- sym_name = bfd_elf_string_from_elf_section
- (input_bfd, symtab_hdr->sh_link, sym->st_name);
-
- signed_p = (ELF_ST_TYPE (sym->st_info) == STT_SRELC);
- }
- else
- {
- /* The symbol is global. */
- struct elf_link_hash_entry * h;
-
- if (elf_bad_symtab (input_bfd))
- continue;
-
- h = sym_hashes [index - locsymcount];
- 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;
-
- if (h->type != STT_RELC && h->type != STT_SRELC)
- continue;
-
- signed_p = (h->type == STT_SRELC);
- sym_name = (char *) h->root.root.string;
- }
-#ifdef DEBUG
- printf ("Encountered a complex symbol!");
- printf (" (input_bfd %s, section %s, reloc %ld\n",
- input_bfd->filename, reloc_sec->name, i);
- printf (" symbol: idx %8.8lx, name %s\n",
- index, sym_name);
- printf (" reloc : info %8.8lx, addr %8.8lx\n",
- rel->r_info, addr);
- printf (" Evaluating '%s' ...\n ", sym_name);
-#endif
- if (eval_symbol (& result, sym_name, & sym_name, input_bfd,
- finfo, addr, section_offset, locsymcount,
- signed_p))
- /* Symbol evaluated OK. Update to absolute value. */
- set_symbol_value (input_bfd, finfo, index, result);
-
- else
- result = FALSE;
- }
-
- if (internal_relocs != elf_section_data (reloc_sec)->relocs)
- free (internal_relocs);
- }
-
- /* If nothing went wrong, then we adjusted
- everything we wanted to adjust. */
- return result;
-}
-