aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog24
-rw-r--r--bfd/elf32-i386.c18
-rw-r--r--bfd/elf32-sparc.c158
-rw-r--r--bfd/elfcode.h111
-rw-r--r--bfd/libelf.h4
5 files changed, 222 insertions, 93 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 2c1e066..414ef40 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,27 @@
+Thu Oct 27 16:59:52 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * libelf.h (struct bfd_elf_section_data): Add field dynindx.
+ * elfcode.h (NAME(bfd_elf,size_dynamic_sections)): Don't finalize
+ the .dynsym, .dynstr or .hash sections until after the backend
+ size_dynamic_sections routine, so that it can add dynamic symbols
+ if it wants to.
+ * elf32-i386.c (elf_i386_adjust_dynamic_symbol): Don't define the
+ symbol to be in the .plt section when generating a shared library
+ if it is a defined symbol.
+ * elf32-sparc.c (elf32_sparc_adjust_dynamic_symbol): Likewise.
+ (elf32_sparc_size_dynamic_sections): When generating a shared
+ library, allocate space for a dynamic symbol for each output
+ section, storing the index in the dynindx field of the ELF section
+ data. Adjust the other dynindx fields to account for this.
+ (elf32_sparc_adjust_dynindx): New static function.
+ (elf32_sparc_relocate_section): When copying a reloc into a shared
+ library, use the original addend as appropriate. Convert an
+ R_SPARC_32 reloc into an R_SPARC_RELATIVE reloc. Use the dynamic
+ symbol index of the output section, not the normal symbol index.
+ (elf32_sparc_finish_dynamic_sections): Don't die if a section does
+ not exist when setting the value of the dynamic tags. Write out
+ a dynamic symbol for each output section.
+
Wed Oct 26 01:15:51 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
* aoutx.h (aout_link_input_section): Don't bother to read or write
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 14f4b71..60c0f45 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -542,9 +542,9 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
if (info->shared
&& (sec->flags & SEC_ALLOC) != 0)
{
- /* When creating a shared object, we must output a
- R_386_RELATIVE reloc for this location. We create a
- reloc section in dynobj and make room for this reloc. */
+ /* When creating a shared object, we must copy these
+ reloc types into the output file. We create a reloc
+ section in dynobj and make room for this reloc. */
if (sreloc == NULL)
{
const char *name;
@@ -647,9 +647,15 @@ elf_i386_adjust_dynamic_symbol (info, h)
if (s->_raw_size == 0)
s->_raw_size += PLT_ENTRY_SIZE;
- /* Set the symbol to this location in the .plt. */
- h->root.u.def.section = s;
- h->root.u.def.value = s->_raw_size;
+ /* If we are not generating a shared library, or if the symbol
+ is not defined, set the symbol to this location in the .plt.
+ This is required to make function pointers compare as equal
+ between the normal executable and the shared library. */
+ if (! info->shared || h->root.type != bfd_link_hash_defined)
+ {
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->_raw_size;
+ }
h->plt_offset = s->_raw_size;
diff --git a/bfd/elf32-sparc.c b/bfd/elf32-sparc.c
index 90130cc..713e855 100644
--- a/bfd/elf32-sparc.c
+++ b/bfd/elf32-sparc.c
@@ -36,6 +36,8 @@ static boolean elf32_sparc_check_relocs
const Elf_Internal_Rela *));
static boolean elf32_sparc_adjust_dynamic_symbol
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
+static boolean elf32_sparc_adjust_dynindx
+ PARAMS ((struct elf_link_hash_entry *, PTR));
static boolean elf32_sparc_size_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
static boolean elf32_sparc_relocate_section
@@ -617,9 +619,15 @@ elf32_sparc_adjust_dynamic_symbol (info, h)
return false;
}
- /* Set the symbol to this location in the .plt. */
- h->root.u.def.section = s;
- h->root.u.def.value = s->_raw_size;
+ /* If we are not generating a shared library, or if the symbol
+ is not defined, set the symbol to this location in the .plt.
+ This is required to make function pointers compare as equal
+ between the normal executable and the shared library. */
+ if (! info->shared || h->root.type != bfd_link_hash_defined)
+ {
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->_raw_size;
+ }
h->plt_offset = s->_raw_size;
@@ -863,6 +871,44 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
}
}
+ /* If we are generating a shared library, we generate a section
+ symbol for each output section. These are local symbols, which
+ means that they must come first in the dynamic symbol table.
+ That means we must increment the dynamic symbol index of every
+ other dynamic symbol. */
+ if (info->shared)
+ {
+ int c, i;
+
+ c = bfd_count_sections (output_bfd);
+ elf_link_hash_traverse (elf_hash_table (info),
+ elf32_sparc_adjust_dynindx,
+ (PTR) &c);
+ elf_hash_table (info)->dynsymcount += c;
+
+ for (i = 1, s = output_bfd->sections; s != NULL; s = s->next, i++)
+ {
+ elf_section_data (s)->dynindx = i;
+ /* These symbols will have no names, so we don't need to
+ fiddle with dynstr_index. */
+ }
+ }
+
+ return true;
+}
+
+/* Increment the index of a dynamic symbol by a given amount. Called
+ via elf_link_hash_traverse. */
+
+static boolean
+elf32_sparc_adjust_dynindx (h, cparg)
+ struct elf_link_hash_entry *h;
+ PTR cparg;
+{
+ int *cp = (int *) cparg;
+
+ if (h->dynindx != -1)
+ h->dynindx += *cp;
return true;
}
@@ -1146,37 +1192,44 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
{
BFD_ASSERT (h->dynindx != -1);
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
- outrel.r_addend = 0;
+ outrel.r_addend = rel->r_addend;
}
else
{
- long indx;
-
- sym = local_syms + r_symndx;
-
- /* If this isn't a section symbol, we need to map it
- to something that is going to be put into the
- dynamic symbols. The case will probably never
- arise. */
- BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_SECTION);
-
- sec = local_sections[r_symndx];
- if (sec != NULL && bfd_is_abs_section (sec))
- indx = 0;
- else if (sec == NULL || sec->owner == NULL)
+ if (r_type == R_SPARC_32)
{
- bfd_set_error (bfd_error_bad_value);
- return false;
+ outrel.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE);
+ outrel.r_addend = relocation + rel->r_addend;
}
else
{
- indx = sec->output_section->target_index;
- if (indx == 0)
- abort ();
+ long indx;
+
+ sym = local_syms + r_symndx;
+
+ BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_SECTION);
+
+ sec = local_sections[r_symndx];
+ if (sec != NULL && bfd_is_abs_section (sec))
+ indx = 0;
+ else if (sec == NULL || sec->owner == NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ else
+ {
+ asection *osec;
+
+ osec = sec->output_section;
+ indx = elf_section_data (osec)->dynindx;
+ if (indx == 0)
+ abort ();
+ }
+
+ outrel.r_info = ELF32_R_INFO (indx, r_type);
+ outrel.r_addend = relocation + rel->r_addend;
}
-
- outrel.r_info = ELF32_R_INFO (indx, r_type);
- outrel.r_addend = sec->output_offset + sym->st_value;
}
bfd_elf32_swap_reloca_out (output_bfd, &outrel,
@@ -1399,15 +1452,19 @@ elf32_sparc_finish_dynamic_sections (output_bfd, info)
asection *s;
s = bfd_get_section_by_name (output_bfd, name);
- BFD_ASSERT (s != NULL);
- if (! size)
- dyn.d_un.d_ptr = s->vma;
+ if (s == NULL)
+ dyn.d_un.d_val = 0;
else
{
- if (s->_cooked_size != 0)
- dyn.d_un.d_val = s->_cooked_size;
+ if (! size)
+ dyn.d_un.d_ptr = s->vma;
else
- dyn.d_un.d_val = s->_raw_size;
+ {
+ if (s->_cooked_size != 0)
+ dyn.d_un.d_val = s->_cooked_size;
+ else
+ dyn.d_un.d_val = s->_raw_size;
+ }
}
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
}
@@ -1442,6 +1499,43 @@ elf32_sparc_finish_dynamic_sections (output_bfd, info)
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
+ if (info->shared)
+ {
+ asection *sdynsym;
+ asection *s;
+ Elf_Internal_Sym sym;
+
+ /* Set up the section symbols for the output sections. */
+
+ sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
+ BFD_ASSERT (sdynsym != NULL);
+
+ sym.st_size = 0;
+ sym.st_name = 0;
+ sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
+ sym.st_other = 0;
+
+ for (s = output_bfd->sections; s != NULL; s = s->next)
+ {
+ int indx;
+
+ sym.st_value = s->vma;
+
+ indx = elf_section_data (s)->this_idx;
+ BFD_ASSERT (indx > 0);
+ sym.st_shndx = indx;
+
+ bfd_elf32_swap_symbol_out (output_bfd, &sym,
+ ((Elf32_External_Sym *) sdynsym->contents
+ + elf_section_data (s)->dynindx));
+ }
+
+ /* Set the sh_info field of the output .dynsym section to the
+ index of the first global symbol. */
+ elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
+ bfd_count_sections (output_bfd) + 1;
+ }
+
return true;
}
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index d1ef2dc..cdb51af 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -4819,62 +4819,11 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info,
if (elf_hash_table (info)->dynamic_sections_created)
{
- size_t dynsymcount;
bfd_size_type strsize;
*sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
BFD_ASSERT (*sinterpptr != NULL || info->shared);
- /* Set the size of the .dynsym and .hash sections. We counted
- the number of dynamic symbols in elf_link_add_object_symbols.
- We will build the contents of .dynsym and .hash when we build
- the final symbol table, because until then we do not know the
- correct value to give the symbols. We built the .dynstr
- section as we went along in elf_link_add_object_symbols. */
- dynsymcount = elf_hash_table (info)->dynsymcount;
- s = bfd_get_section_by_name (dynobj, ".dynsym");
- BFD_ASSERT (s != NULL);
- s->_raw_size = dynsymcount * sizeof (Elf_External_Sym);
- s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
- if (s->contents == NULL && s->_raw_size != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- /* The first entry in .dynsym is a dummy symbol. */
- isym.st_value = 0;
- isym.st_size = 0;
- isym.st_name = 0;
- isym.st_info = 0;
- isym.st_other = 0;
- isym.st_shndx = 0;
- elf_swap_symbol_out (output_bfd, &isym,
- (Elf_External_Sym *) s->contents);
-
- for (i = 0; elf_buckets[i] != 0; i++)
- {
- bucketcount = elf_buckets[i];
- if (dynsymcount < elf_buckets[i + 1])
- break;
- }
-
- s = bfd_get_section_by_name (dynobj, ".hash");
- BFD_ASSERT (s != NULL);
- s->_raw_size = (2 + bucketcount + dynsymcount) * (ARCH_SIZE / 8);
- s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
- if (s->contents == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- memset (s->contents, 0, s->_raw_size);
-
- put_word (output_bfd, bucketcount, s->contents);
- put_word (output_bfd, dynsymcount, s->contents + (ARCH_SIZE / 8));
-
- elf_hash_table (info)->bucketcount = bucketcount;
-
if (soname != NULL)
{
bfd_size_type indx;
@@ -4897,10 +4846,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info,
return false;
}
- s = bfd_get_section_by_name (dynobj, ".dynstr");
- BFD_ASSERT (s != NULL);
- s->_raw_size = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
-
/* Find all symbols which were defined in a dynamic object and make
the backend pick a reasonable value for them. */
elf_link_hash_traverse (elf_hash_table (info),
@@ -4938,6 +4883,62 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info,
if (elf_hash_table (info)->dynamic_sections_created)
{
+ size_t dynsymcount;
+
+ /* Set the size of the .dynsym and .hash sections. We counted
+ the number of dynamic symbols in elf_link_add_object_symbols.
+ We will build the contents of .dynsym and .hash when we build
+ the final symbol table, because until then we do not know the
+ correct value to give the symbols. We built the .dynstr
+ section as we went along in elf_link_add_object_symbols. */
+ dynsymcount = elf_hash_table (info)->dynsymcount;
+ s = bfd_get_section_by_name (dynobj, ".dynsym");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size = dynsymcount * sizeof (Elf_External_Sym);
+ s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
+ if (s->contents == NULL && s->_raw_size != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+
+ /* The first entry in .dynsym is a dummy symbol. */
+ isym.st_value = 0;
+ isym.st_size = 0;
+ isym.st_name = 0;
+ isym.st_info = 0;
+ isym.st_other = 0;
+ isym.st_shndx = 0;
+ elf_swap_symbol_out (output_bfd, &isym,
+ (Elf_External_Sym *) s->contents);
+
+ for (i = 0; elf_buckets[i] != 0; i++)
+ {
+ bucketcount = elf_buckets[i];
+ if (dynsymcount < elf_buckets[i + 1])
+ break;
+ }
+
+ s = bfd_get_section_by_name (dynobj, ".hash");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size = (2 + bucketcount + dynsymcount) * (ARCH_SIZE / 8);
+ s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
+ if (s->contents == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ memset (s->contents, 0, s->_raw_size);
+
+ put_word (output_bfd, bucketcount, s->contents);
+ put_word (output_bfd, dynsymcount, s->contents + (ARCH_SIZE / 8));
+
+ elf_hash_table (info)->bucketcount = bucketcount;
+
+ s = bfd_get_section_by_name (dynobj, ".dynstr");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
+
if (! elf_add_dynamic_entry (info, DT_NULL, 0))
return false;
}
diff --git a/bfd/libelf.h b/bfd/libelf.h
index b752946..3bbde89 100644
--- a/bfd/libelf.h
+++ b/bfd/libelf.h
@@ -420,6 +420,10 @@ struct bfd_elf_section_data {
rather than RELA, all the r_addend fields will be zero. This
pointer may be NULL. It is used by the backend linker. */
Elf_Internal_Rela *relocs;
+ /* Used by the backend linker when generating a shared library to
+ record the dynamic symbol index for a section symbol
+ corresponding to this section. */
+ long dynindx;
};
#define elf_section_data(sec) ((struct bfd_elf_section_data*)sec->used_by_bfd)