* 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:
parent
c51975113d
commit
14cac507a8
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
/* 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;
|
||||
|
||||
|
|
|
@ -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. */
|
||||
/* 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,7 +1192,14 @@ 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
|
||||
{
|
||||
if (r_type == R_SPARC_32)
|
||||
{
|
||||
outrel.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE);
|
||||
outrel.r_addend = relocation + rel->r_addend;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1154,10 +1207,6 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
|
||||
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];
|
||||
|
@ -1170,13 +1219,17 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
}
|
||||
else
|
||||
{
|
||||
indx = sec->output_section->target_index;
|
||||
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 = sec->output_offset + sym->st_value;
|
||||
outrel.r_addend = relocation + rel->r_addend;
|
||||
}
|
||||
}
|
||||
|
||||
bfd_elf32_swap_reloca_out (output_bfd, &outrel,
|
||||
|
@ -1399,7 +1452,10 @@ elf32_sparc_finish_dynamic_sections (output_bfd, info)
|
|||
asection *s;
|
||||
|
||||
s = bfd_get_section_by_name (output_bfd, name);
|
||||
BFD_ASSERT (s != NULL);
|
||||
if (s == NULL)
|
||||
dyn.d_un.d_val = 0;
|
||||
else
|
||||
{
|
||||
if (! size)
|
||||
dyn.d_un.d_ptr = s->vma;
|
||||
else
|
||||
|
@ -1409,6 +1465,7 @@ elf32_sparc_finish_dynamic_sections (output_bfd, info)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
121
bfd/elfcode.h
121
bfd/elfcode.h
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue