+ Elf_Internal_Shdr *rel_hdr;
+ PTR alloc1 = NULL;
+ Elf_Internal_Rela *alloc2 = NULL;
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ if (elf_section_data (o)->relocs != NULL)
+ return elf_section_data (o)->relocs;
+
+ if (o->reloc_count == 0)
+ return NULL;
+
+ rel_hdr = &elf_section_data (o)->rel_hdr;
+
+ if (internal_relocs == NULL)
+ {
+ bfd_size_type size;
+
+ size = o->reloc_count;
+ size *= bed->s->int_rels_per_ext_rel * sizeof (Elf_Internal_Rela);
+ if (keep_memory)
+ internal_relocs = (Elf_Internal_Rela *) bfd_alloc (abfd, size);
+ else
+ internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_malloc (size);
+ if (internal_relocs == NULL)
+ goto error_return;
+ }
+
+ if (external_relocs == NULL)
+ {
+ bfd_size_type size = rel_hdr->sh_size;
+
+ if (elf_section_data (o)->rel_hdr2)
+ size += elf_section_data (o)->rel_hdr2->sh_size;
+ alloc1 = (PTR) bfd_malloc (size);
+ if (alloc1 == NULL)
+ goto error_return;
+ external_relocs = alloc1;
+ }
+
+ if (!elf_link_read_relocs_from_section (abfd, rel_hdr,
+ external_relocs,
+ internal_relocs))
+ goto error_return;
+ if (!elf_link_read_relocs_from_section
+ (abfd,
+ elf_section_data (o)->rel_hdr2,
+ ((bfd_byte *) external_relocs) + rel_hdr->sh_size,
+ internal_relocs + (NUM_SHDR_ENTRIES (rel_hdr)
+ * bed->s->int_rels_per_ext_rel)))
+ goto error_return;
+
+ /* Cache the results for next time, if we can. */
+ if (keep_memory)
+ elf_section_data (o)->relocs = internal_relocs;
+
+ if (alloc1 != NULL)
+ free (alloc1);
+
+ /* Don't free alloc2, since if it was allocated we are passing it
+ back (under the name of internal_relocs). */
+
+ return internal_relocs;
+
+ error_return:
+ if (alloc1 != NULL)
+ free (alloc1);
+ if (alloc2 != NULL)
+ free (alloc2);
+ return NULL;
+}
+
+/* Compute the size of, and allocate space for, REL_HDR which is the
+ section header for a section containing relocations for O. */
+
+bfd_boolean
+_bfd_elf_link_size_reloc_section (abfd, rel_hdr, o)
+ bfd *abfd;
+ Elf_Internal_Shdr *rel_hdr;
+ asection *o;
+{
+ bfd_size_type reloc_count;
+ bfd_size_type num_rel_hashes;
+
+ /* Figure out how many relocations there will be. */
+ if (rel_hdr == &elf_section_data (o)->rel_hdr)
+ reloc_count = elf_section_data (o)->rel_count;
+ else
+ reloc_count = elf_section_data (o)->rel_count2;
+
+ num_rel_hashes = o->reloc_count;
+ if (num_rel_hashes < reloc_count)
+ num_rel_hashes = reloc_count;
+
+ /* That allows us to calculate the size of the section. */
+ rel_hdr->sh_size = rel_hdr->sh_entsize * reloc_count;
+
+ /* The contents field must last into write_object_contents, so we
+ allocate it with bfd_alloc rather than malloc. Also since we
+ cannot be sure that the contents will actually be filled in,
+ we zero the allocated space. */
+ rel_hdr->contents = (PTR) bfd_zalloc (abfd, rel_hdr->sh_size);
+ if (rel_hdr->contents == NULL && rel_hdr->sh_size != 0)
+ return FALSE;
+
+ /* We only allocate one set of hash entries, so we only do it the
+ first time we are called. */
+ if (elf_section_data (o)->rel_hashes == NULL
+ && num_rel_hashes)
+ {
+ struct elf_link_hash_entry **p;
+
+ p = ((struct elf_link_hash_entry **)
+ bfd_zmalloc (num_rel_hashes
+ * sizeof (struct elf_link_hash_entry *)));
+ if (p == NULL)
+ return FALSE;
+
+ elf_section_data (o)->rel_hashes = p;
+ }
+
+ return TRUE;
+}
+
+/* Copy the relocations indicated by the INTERNAL_RELOCS (which
+ originated from the section given by INPUT_REL_HDR) to the
+ OUTPUT_BFD. */
+
+bfd_boolean
+_bfd_elf_link_output_relocs (output_bfd, input_section, input_rel_hdr,
+ internal_relocs)
+ bfd *output_bfd;
+ asection *input_section;
+ Elf_Internal_Shdr *input_rel_hdr;
+ Elf_Internal_Rela *internal_relocs;
+{
+ Elf_Internal_Rela *irela;
+ Elf_Internal_Rela *irelaend;
+ bfd_byte *erel;
+ Elf_Internal_Shdr *output_rel_hdr;
+ asection *output_section;
+ unsigned int *rel_countp = NULL;
+ struct elf_backend_data *bed;
+ void (*swap_out) PARAMS ((bfd *, const Elf_Internal_Rela *, bfd_byte *));
+
+ output_section = input_section->output_section;
+ output_rel_hdr = NULL;
+
+ if (elf_section_data (output_section)->rel_hdr.sh_entsize
+ == input_rel_hdr->sh_entsize)
+ {
+ output_rel_hdr = &elf_section_data (output_section)->rel_hdr;
+ rel_countp = &elf_section_data (output_section)->rel_count;
+ }
+ else if (elf_section_data (output_section)->rel_hdr2
+ && (elf_section_data (output_section)->rel_hdr2->sh_entsize
+ == input_rel_hdr->sh_entsize))
+ {
+ output_rel_hdr = elf_section_data (output_section)->rel_hdr2;
+ rel_countp = &elf_section_data (output_section)->rel_count2;
+ }
+ else
+ {
+ (*_bfd_error_handler)
+ (_("%s: relocation size mismatch in %s section %s"),
+ bfd_get_filename (output_bfd),
+ bfd_archive_filename (input_section->owner),
+ input_section->name);
+ bfd_set_error (bfd_error_wrong_object_format);
+ return FALSE;
+ }
+
+ bed = get_elf_backend_data (output_bfd);
+ if (input_rel_hdr->sh_entsize == bed->s->sizeof_rel)
+ swap_out = bed->s->swap_reloc_out;
+ else if (input_rel_hdr->sh_entsize == bed->s->sizeof_rela)
+ swap_out = bed->s->swap_reloca_out;
+ else
+ abort ();
+
+ erel = output_rel_hdr->contents;
+ erel += *rel_countp * input_rel_hdr->sh_entsize;
+ irela = internal_relocs;
+ irelaend = irela + (NUM_SHDR_ENTRIES (input_rel_hdr)
+ * bed->s->int_rels_per_ext_rel);
+ while (irela < irelaend)
+ {
+ (*swap_out) (output_bfd, irela, erel);
+ irela += bed->s->int_rels_per_ext_rel;
+ erel += input_rel_hdr->sh_entsize;
+ }
+
+ /* Bump the counter, so that we know where to add the next set of
+ relocations. */
+ *rel_countp += NUM_SHDR_ENTRIES (input_rel_hdr);
+
+ return TRUE;
+}
+\f
+/* Fix up the flags for a symbol. This handles various cases which
+ can only be fixed after all the input files are seen. This is
+ currently called by both adjust_dynamic_symbol and
+ assign_sym_version, which is unnecessary but perhaps more robust in
+ the face of future changes. */
+
+bfd_boolean
+_bfd_elf_fix_symbol_flags (h, eif)
+ struct elf_link_hash_entry *h;
+ struct elf_info_failed *eif;
+{
+ /* If this symbol was mentioned in a non-ELF file, try to set
+ DEF_REGULAR and REF_REGULAR correctly. This is the only way to
+ permit a non-ELF file to correctly refer to a symbol defined in
+ an ELF dynamic object. */
+ if ((h->elf_link_hash_flags & ELF_LINK_NON_ELF) != 0)
+ {
+ while (h->root.type == bfd_link_hash_indirect)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ if (h->root.type != bfd_link_hash_defined
+ && h->root.type != bfd_link_hash_defweak)
+ h->elf_link_hash_flags |= (ELF_LINK_HASH_REF_REGULAR
+ | ELF_LINK_HASH_REF_REGULAR_NONWEAK);
+ else
+ {
+ if (h->root.u.def.section->owner != NULL
+ && (bfd_get_flavour (h->root.u.def.section->owner)
+ == bfd_target_elf_flavour))
+ h->elf_link_hash_flags |= (ELF_LINK_HASH_REF_REGULAR
+ | ELF_LINK_HASH_REF_REGULAR_NONWEAK);
+ else
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ }
+
+ if (h->dynindx == -1
+ && ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ || (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0))
+ {
+ if (! _bfd_elf_link_record_dynamic_symbol (eif->info, h))
+ {
+ eif->failed = TRUE;
+ return FALSE;
+ }
+ }
+ }
+ else
+ {
+ /* Unfortunately, ELF_LINK_NON_ELF is only correct if the symbol
+ was first seen in a non-ELF file. Fortunately, if the symbol
+ was first seen in an ELF file, we're probably OK unless the
+ symbol was defined in a non-ELF file. Catch that case here.
+ FIXME: We're still in trouble if the symbol was first seen in
+ a dynamic object, and then later in a non-ELF regular object. */
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
+ && (h->root.u.def.section->owner != NULL
+ ? (bfd_get_flavour (h->root.u.def.section->owner)
+ != bfd_target_elf_flavour)
+ : (bfd_is_abs_section (h->root.u.def.section)
+ && (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_DYNAMIC) == 0)))
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ }
+
+ /* If this is a final link, and the symbol was defined as a common
+ symbol in a regular object file, and there was no definition in
+ any dynamic object, then the linker will have allocated space for
+ the symbol in a common section but the ELF_LINK_HASH_DEF_REGULAR
+ flag will not have been set. */
+ if (h->root.type == bfd_link_hash_defined
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) != 0
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
+ && (h->root.u.def.section->owner->flags & DYNAMIC) == 0)
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+
+ /* If -Bsymbolic was used (which means to bind references to global
+ symbols to the definition within the shared object), and this
+ symbol was defined in a regular object, then it actually doesn't
+ need a PLT entry. Likewise, if the symbol has non-default
+ visibility. If the symbol has hidden or internal visibility, we
+ will force it local. */
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0
+ && eif->info->shared
+ && is_elf_hash_table (eif->info)
+ && (eif->info->symbolic
+ || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
+ {
+ struct elf_backend_data *bed;
+ bfd_boolean force_local;
+
+ bed = get_elf_backend_data (elf_hash_table (eif->info)->dynobj);
+
+ force_local = (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
+ || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN);
+ (*bed->elf_backend_hide_symbol) (eif->info, h, force_local);
+ }
+
+ /* If a weak undefined symbol has non-default visibility, we also
+ hide it from the dynamic linker. */
+ if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+ && h->root.type == bfd_link_hash_undefweak)
+ {
+ struct elf_backend_data *bed;
+ bed = get_elf_backend_data (elf_hash_table (eif->info)->dynobj);
+ (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
+ }
+
+ /* If this is a weak defined symbol in a dynamic object, and we know
+ the real definition in the dynamic object, copy interesting flags
+ over to the real definition. */
+ if (h->weakdef != NULL)
+ {
+ struct elf_link_hash_entry *weakdef;
+
+ weakdef = h->weakdef;
+ if (h->root.type == bfd_link_hash_indirect)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ BFD_ASSERT (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak);
+ BFD_ASSERT (weakdef->root.type == bfd_link_hash_defined
+ || weakdef->root.type == bfd_link_hash_defweak);
+ BFD_ASSERT (weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC);
+
+ /* If the real definition is defined by a regular object file,
+ don't do anything special. See the longer description in
+ _bfd_elf_adjust_dynamic_symbol, below. */
+ if ((weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
+ h->weakdef = NULL;
+ else
+ {
+ struct elf_backend_data *bed;
+
+ bed = get_elf_backend_data (elf_hash_table (eif->info)->dynobj);
+ (*bed->elf_backend_copy_indirect_symbol) (bed, weakdef, h);
+ }
+ }
+
+ return TRUE;
+}
+
+/* Make the backend pick a good value for a dynamic symbol. This is
+ called via elf_link_hash_traverse, and also calls itself
+ recursively. */
+
+bfd_boolean
+_bfd_elf_adjust_dynamic_symbol (h, data)
+ struct elf_link_hash_entry *h;
+ PTR data;
+{
+ struct elf_info_failed *eif = (struct elf_info_failed *) data;
+ bfd *dynobj;
+ struct elf_backend_data *bed;
+
+ if (! is_elf_hash_table (eif->info))
+ return FALSE;
+
+ if (h->root.type == bfd_link_hash_warning)
+ {
+ h->plt = elf_hash_table (eif->info)->init_offset;
+ h->got = elf_hash_table (eif->info)->init_offset;
+
+ /* When warning symbols are created, they **replace** the "real"
+ entry in the hash table, thus we never get to see the real
+ symbol in a hash traversal. So look at it now. */
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ }
+
+ /* Ignore indirect symbols. These are added by the versioning code. */
+ if (h->root.type == bfd_link_hash_indirect)
+ return TRUE;
+
+ /* Fix the symbol flags. */
+ if (! _bfd_elf_fix_symbol_flags (h, eif))
+ return FALSE;
+
+ /* If this symbol does not require a PLT entry, and it is not
+ defined by a dynamic object, or is not referenced by a regular
+ object, ignore it. We do have to handle a weak defined symbol,
+ even if no regular object refers to it, if we decided to add it
+ to the dynamic symbol table. FIXME: Do we normally need to worry
+ about symbols which are defined by one dynamic object and
+ referenced by another one? */
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) == 0
+ && ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
+ || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
+ || ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0
+ && (h->weakdef == NULL || h->weakdef->dynindx == -1))))
+ {
+ h->plt = elf_hash_table (eif->info)->init_offset;
+ return TRUE;
+ }
+
+ /* If we've already adjusted this symbol, don't do it again. This
+ can happen via a recursive call. */
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_DYNAMIC_ADJUSTED) != 0)
+ return TRUE;
+
+ /* Don't look at this symbol again. Note that we must set this
+ after checking the above conditions, because we may look at a
+ symbol once, decide not to do anything, and then get called
+ recursively later after REF_REGULAR is set below. */
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DYNAMIC_ADJUSTED;
+
+ /* If this is a weak definition, and we know a real definition, and
+ the real symbol is not itself defined by a regular object file,
+ then get a good value for the real definition. We handle the
+ real symbol first, for the convenience of the backend routine.
+
+ Note that there is a confusing case here. If the real definition
+ is defined by a regular object file, we don't get the real symbol
+ from the dynamic object, but we do get the weak symbol. If the
+ processor backend uses a COPY reloc, then if some routine in the
+ dynamic object changes the real symbol, we will not see that
+ change in the corresponding weak symbol. This is the way other
+ ELF linkers work as well, and seems to be a result of the shared
+ library model.
+
+ I will clarify this issue. Most SVR4 shared libraries define the
+ variable _timezone and define timezone as a weak synonym. The
+ tzset call changes _timezone. If you write
+ extern int timezone;
+ int _timezone = 5;
+ int main () { tzset (); printf ("%d %d\n", timezone, _timezone); }
+ you might expect that, since timezone is a synonym for _timezone,
+ the same number will print both times. However, if the processor
+ backend uses a COPY reloc, then actually timezone will be copied
+ into your process image, and, since you define _timezone
+ yourself, _timezone will not. Thus timezone and _timezone will
+ wind up at different memory locations. The tzset call will set
+ _timezone, leaving timezone unchanged. */
+
+ if (h->weakdef != NULL)
+ {
+ /* If we get to this point, we know there is an implicit
+ reference by a regular object file via the weak symbol H.
+ FIXME: Is this really true? What if the traversal finds
+ H->WEAKDEF before it finds H? */
+ h->weakdef->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
+
+ if (! _bfd_elf_adjust_dynamic_symbol (h->weakdef, (PTR) eif))
+ return FALSE;
+ }
+
+ /* If a symbol has no type and no size and does not require a PLT
+ entry, then we are probably about to do the wrong thing here: we
+ are probably going to create a COPY reloc for an empty object.
+ This case can arise when a shared object is built with assembly
+ code, and the assembly code fails to set the symbol type. */
+ if (h->size == 0
+ && h->type == STT_NOTYPE
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) == 0)
+ (*_bfd_error_handler)
+ (_("warning: type and size of dynamic symbol `%s' are not defined"),
+ h->root.root.string);
+
+ dynobj = elf_hash_table (eif->info)->dynobj;
+ bed = get_elf_backend_data (dynobj);
+ if (! (*bed->elf_backend_adjust_dynamic_symbol) (eif->info, h))
+ {
+ eif->failed = TRUE;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Adjust all external symbols pointing into SEC_MERGE sections
+ to reflect the object merging within the sections. */
+
+bfd_boolean
+_bfd_elf_link_sec_merge_syms (h, data)
+ struct elf_link_hash_entry *h;
+ PTR data;
+{
+ asection *sec;
+
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && ((sec = h->root.u.def.section)->flags & SEC_MERGE)
+ && sec->sec_info_type == ELF_INFO_TYPE_MERGE)
+ {
+ bfd *output_bfd = (bfd *) data;
+
+ h->root.u.def.value =
+ _bfd_merged_section_offset (output_bfd,
+ &h->root.u.def.section,
+ elf_section_data (sec)->sec_info,
+ h->root.u.def.value, (bfd_vma) 0);
+ }
+
+ return TRUE;
+}
+
+/* Returns false if the symbol referred to by H should be considered
+ to resolve local to the current module, and true if it should be
+ considered to bind dynamically. */
+
+bfd_boolean
+_bfd_elf_dynamic_symbol_p (h, info, ignore_protected)
+ struct elf_link_hash_entry *h;
+ struct bfd_link_info *info;
+ bfd_boolean ignore_protected;
+{
+ bfd_boolean binding_stays_local_p;
+
+ if (h == NULL)
+ return FALSE;
+
+ 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 it was forced local, then clearly it's not dynamic. */
+ if (h->dynindx == -1)
+ return FALSE;
+ if (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)
+ return FALSE;
+
+ /* Identify the cases where name binding rules say that a
+ visible symbol resolves locally. */
+ binding_stays_local_p = info->executable || info->symbolic;
+
+ switch (ELF_ST_VISIBILITY (h->other))
+ {
+ case STV_INTERNAL:
+ case STV_HIDDEN:
+ return FALSE;
+
+ case STV_PROTECTED:
+ /* Proper resolution for function pointer equality may require
+ that these symbols perhaps be resolved dynamically, even though
+ we should be resolving them to the current module. */
+ if (!ignore_protected)
+ binding_stays_local_p = TRUE;
+ break;
+
+ default:
+ /* With STV_DEFAULT, weak symbols do not bind locally. */
+ if (h->root.type == bfd_link_hash_undefweak
+ || h->root.type == bfd_link_hash_defweak)
+ return TRUE;
+ break;
+ }
+
+ /* If it isn't defined locally, then clearly it's dynamic. */
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ return TRUE;
+
+ /* Otherwise, the symbol is dynamic if binding rules don't tell
+ us that it remains local. */
+ return !binding_stays_local_p;
+}
+
+/* Return true if the symbol referred to by H should be considered
+ to resolve local to the current module, and false otherwise. Differs
+ from (the inverse of) _bfd_elf_dynamic_symbol_p in the treatment of
+ undefined symbols and weak symbols. */
+
+bfd_boolean
+_bfd_elf_symbol_refs_local_p (h, info, local_protected)
+ struct elf_link_hash_entry *h;
+ struct bfd_link_info *info;
+ bfd_boolean local_protected;
+{
+ /* If it's a local sym, of course we resolve locally. */
+ if (h == NULL)
+ return TRUE;
+
+ /* If we don't have a definition in a regular file, then we can't
+ resolve locally. The sym is either undefined or dynamic. */
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ return FALSE;
+
+ /* Forced local symbols resolve locally. */
+ if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+ return TRUE;
+
+ /* As do non-dynamic symbols. */
+ if (h->dynindx == -1)
+ return TRUE;
+
+ /* At this point, we know the symbol is defined and dynamic. In an
+ executable it must resolve locally, likewise when building symbolic
+ shared libraries. */
+ if (info->executable || info->symbolic)
+ return TRUE;
+
+ /* Now deal with defined dynamic symbols in shared libraries. Ones
+ with default visibility might not resolve locally. */
+ if (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
+ return FALSE;
+
+ /* However, STV_HIDDEN or STV_INTERNAL ones must be local. */
+ if (ELF_ST_VISIBILITY (h->other) != STV_PROTECTED)
+ return TRUE;
+
+ /* Function pointer equality tests may require that STV_PROTECTED
+ symbols be treated as dynamic symbols, even when we know that the
+ dynamic linker will resolve them locally. */
+ return local_protected;