else
newdyn = false;
- if (oldbfd == NULL || (oldbfd->flags & DYNAMIC) == 0)
- olddyn = false;
+ if (oldbfd != NULL)
+ olddyn = (oldbfd->flags & DYNAMIC) != 0;
else
- olddyn = true;
+ {
+ asection *hsec;
+
+ /* This code handles the special SHN_MIPS_{TEXT,DATA} section
+ indices used by MIPS ELF. */
+ switch (h->root.type)
+ {
+ default:
+ hsec = NULL;
+ break;
+
+ case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
+ hsec = h->root.u.def.section;
+ break;
+
+ case bfd_link_hash_common:
+ hsec = h->root.u.c.p->section;
+ break;
+ }
+
+ if (hsec == NULL)
+ olddyn = false;
+ else
+ olddyn = (hsec->symbol->flags & BSF_DYNAMIC) != 0;
+ }
/* NEWDEF and OLDDEF indicate whether the new or old symbol,
respectively, appear to be a definition rather than reference. */
goto error_return;
link = elf_elfsections (abfd)[elfsec]->sh_link;
+ {
+ /* The shared libraries distributed with hpux11 have a bogus
+ sh_link field for the ".dynamic" section. This code detects
+ when LINK refers to a section that is not a string table and
+ tries to find the string table for the ".dynsym" section
+ instead. */
+ Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[link];
+ if (hdr->sh_type != SHT_STRTAB)
+ {
+ asection *s = bfd_get_section_by_name (abfd, ".dynsym");
+ int elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
+ if (elfsec == -1)
+ goto error_return;
+ link = elf_elfsections (abfd)[elfsec]->sh_link;
+ }
+ }
+
extdyn = dynbuf;
extdynend = extdyn + s->_raw_size / sizeof (Elf_External_Dyn);
for (; extdyn < extdynend; extdyn++)
h->verinfo.verdef = NULL;
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
- h->type = STT_OBJECT;
+
+ /* When possible, keep the original type of the symbol */
+ if (h->type == STT_NOTYPE)
+ h->type = STT_OBJECT;
if (((h->elf_link_hash_flags & (ELF_LINK_HASH_DEF_DYNAMIC
| ELF_LINK_HASH_REF_DYNAMIC)) != 0
{
/* There is an implicit reference by a regular object file
via the weak symbol. */
- weakdef->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
- if (h->weakdef->elf_link_hash_flags
- & ELF_LINK_HASH_REF_REGULAR_NONWEAK)
- weakdef->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR_NONWEAK;
+ weakdef->elf_link_hash_flags |=
+ (ELF_LINK_HASH_REF_REGULAR
+ | (h->elf_link_hash_flags
+ & (ELF_LINK_HASH_REF_REGULAR_NONWEAK
+ | ELF_LINK_NON_GOT_REF)));
if (! elf_adjust_dynamic_symbol (weakdef, (PTR) eif))
return false;
}
asection *o;
{
register struct elf_link_hash_entry **p, **pend;
+ unsigned reloc_count;
+
+ /* 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;
- /* We are overestimating the size required for the relocation
- sections, in the case that we are using both REL and RELA
- relocations for a single section. In that case, RELOC_COUNT will
- be the total number of relocations required, and we allocate
- space for that many REL relocations as well as that many RELA
- relocations. This approximation is wasteful of disk space.
- However, until we keep track of how many of each kind of
- relocation is required, it's difficult to calculate the right
- value. */
- rel_hdr->sh_size = rel_hdr->sh_entsize * o->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. */
rel_hdr->contents = (PTR) bfd_alloc (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)
+ {
+ p = ((struct elf_link_hash_entry **)
+ bfd_malloc (o->reloc_count
+ * sizeof (struct elf_link_hash_entry *)));
+ if (p == NULL && o->reloc_count != 0)
+ return false;
- p = ((struct elf_link_hash_entry **)
- bfd_malloc (o->reloc_count
- * sizeof (struct elf_link_hash_entry *)));
- if (p == NULL && o->reloc_count != 0)
- return false;
-
- elf_section_data (o)->rel_hashes = p;
- pend = p + o->reloc_count;
- for (; p < pend; p++)
- *p = NULL;
+ elf_section_data (o)->rel_hashes = p;
+ pend = p + o->reloc_count;
+ for (; p < pend; p++)
+ *p = NULL;
+ }
return true;
}
if (! _bfd_elf_compute_section_file_positions (abfd, info))
goto error_return;
+ /* Figure out how many relocations we will have in each section.
+ Just using RELOC_COUNT isn't good enough since that doesn't
+ maintain a separate value for REL vs. RELA relocations. */
+ if (info->relocateable)
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ for (o = sub->sections; o != NULL; o = o->next)
+ {
+ asection *output_section;
+
+ if (! o->linker_mark)
+ {
+ /* This section was omitted from the link. */
+ continue;
+ }
+
+ output_section = o->output_section;
+
+ if (output_section != NULL
+ && (o->flags & SEC_RELOC) != 0)
+ {
+ struct bfd_elf_section_data *esdi
+ = elf_section_data (o);
+ struct bfd_elf_section_data *esdo
+ = elf_section_data (output_section);
+ unsigned int *rel_count;
+ unsigned int *rel_count2;
+
+ /* We must be careful to add the relocation froms the
+ input section to the right output count. */
+ if (esdi->rel_hdr.sh_entsize == esdo->rel_hdr.sh_entsize)
+ {
+ rel_count = &esdo->rel_count;
+ rel_count2 = &esdo->rel_count2;
+ }
+ else
+ {
+ rel_count = &esdo->rel_count2;
+ rel_count2 = &esdo->rel_count;
+ }
+
+ *rel_count += (esdi->rel_hdr.sh_size
+ / esdi->rel_hdr.sh_entsize);
+ if (esdi->rel_hdr2)
+ *rel_count2 += (esdi->rel_hdr2->sh_size
+ / esdi->rel_hdr2->sh_entsize);
+ }
+ }
+
/* That created the reloc sections. Set their sizes, and assign
them file positions, and allocate some buffers. */
for (o = abfd->sections; o != NULL; o = o->next)
o))
goto error_return;
}
+
+ /* Now, reset REL_COUNT and REL_COUNT2 so that we can use them
+ to count upwards while actually outputting the relocations. */
+ elf_section_data (o)->rel_count = 0;
+ elf_section_data (o)->rel_count2 = 0;
}
_bfd_elf_assign_file_positions_for_relocs (abfd);
{
asection *s;
+ sym.st_size = e->isym.st_size;
+ sym.st_other = e->isym.st_other;
+
/* Copy the internal symbol as is.
Note that we saved a word of storage and overwrote
the original st_name with the dynstr_index. */
return false;
oldbytes = (h->vtable_entries_size/FILE_ALIGN + 1) * sizeof(boolean);
- memset (ptr + oldbytes, 0, bytes - oldbytes);
+ memset (((char *)ptr) + oldbytes, 0, bytes - oldbytes);
}
else
{