* 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.
This commit is contained in:
Ian Lance Taylor 1994-10-27 21:25:31 +00:00
parent c51975113d
commit 14cac507a8
5 changed files with 227 additions and 98 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;
outrel.r_info = ELF32_R_INFO (indx, r_type);
outrel.r_addend = sec->output_offset + sym->st_value;
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;
}
}
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;
}

View File

@ -4819,12 +4819,72 @@ 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);
if (soname != NULL)
{
bfd_size_type indx;
indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, soname,
true, true);
if (indx == (bfd_size_type) -1
|| ! elf_add_dynamic_entry (info, DT_SONAME, indx))
return false;
}
if (rpath != NULL)
{
bfd_size_type indx;
indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, rpath,
true, true);
if (indx == (bfd_size_type) -1
|| ! elf_add_dynamic_entry (info, DT_RPATH, indx))
return false;
}
/* 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),
elf_adjust_dynamic_symbol,
(PTR) info);
/* Add some entries to the .dynamic section. We fill in some of the
values later, in elf_bfd_final_link, but we must add the entries
now so that we know the final size of the .dynamic section. */
if (bfd_get_section_by_name (output_bfd, ".init") != NULL)
{
if (! elf_add_dynamic_entry (info, DT_INIT, 0))
return false;
}
if (bfd_get_section_by_name (output_bfd, ".fini") != NULL)
{
if (! elf_add_dynamic_entry (info, DT_FINI, 0))
return false;
}
strsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
if (! elf_add_dynamic_entry (info, DT_HASH, 0)
|| ! elf_add_dynamic_entry (info, DT_STRTAB, 0)
|| ! elf_add_dynamic_entry (info, DT_SYMTAB, 0)
|| ! elf_add_dynamic_entry (info, DT_STRSZ, strsize)
|| ! elf_add_dynamic_entry (info, DT_SYMENT,
sizeof (Elf_External_Sym)))
return false;
}
/* The backend must work out the sizes of all the other dynamic
sections. */
bed = get_elf_backend_data (output_bfd);
if (! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
return false;
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
@ -4875,69 +4935,10 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info,
elf_hash_table (info)->bucketcount = bucketcount;
if (soname != NULL)
{
bfd_size_type indx;
indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, soname,
true, true);
if (indx == (bfd_size_type) -1
|| ! elf_add_dynamic_entry (info, DT_SONAME, indx))
return false;
}
if (rpath != NULL)
{
bfd_size_type indx;
indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, rpath,
true, true);
if (indx == (bfd_size_type) -1
|| ! elf_add_dynamic_entry (info, DT_RPATH, indx))
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),
elf_adjust_dynamic_symbol,
(PTR) info);
/* Add some entries to the .dynamic section. We fill in some of the
values later, in elf_bfd_final_link, but we must add the entries
now so that we know the final size of the .dynamic section. */
if (bfd_get_section_by_name (output_bfd, ".init") != NULL)
{
if (! elf_add_dynamic_entry (info, DT_INIT, 0))
return false;
}
if (bfd_get_section_by_name (output_bfd, ".fini") != NULL)
{
if (! elf_add_dynamic_entry (info, DT_FINI, 0))
return false;
}
strsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
if (! elf_add_dynamic_entry (info, DT_HASH, 0)
|| ! elf_add_dynamic_entry (info, DT_STRTAB, 0)
|| ! elf_add_dynamic_entry (info, DT_SYMTAB, 0)
|| ! elf_add_dynamic_entry (info, DT_STRSZ, strsize)
|| ! elf_add_dynamic_entry (info, DT_SYMENT,
sizeof (Elf_External_Sym)))
return false;
}
/* The backend must work out the sizes of all the other dynamic
sections. */
bed = get_elf_backend_data (output_bfd);
if (! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
return false;
if (elf_hash_table (info)->dynamic_sections_created)
{
if (! elf_add_dynamic_entry (info, DT_NULL, 0))
return false;
}

View File

@ -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)