* sunos.c (sunos_add_one_symbol): Don't change

bfd_link_hash_common to bfd_link_hash_new, since it may be on the
	undef list.
	(bfd_sunos_record_link_assignment): Don't put __DYNAMIC in the
	dynamic symbols when creating a shared library.
	(sunos_scan_ext_relocs): Handle relocs correctly when creating a
	shared library.
	(sunos_scan_dynamic_symbol): Don't mark the __DYNAMIC symbol as
	written even if it is not defined in a regular object.
	(sunos_write_dynamic_symbol): Use plt_offset for the address of
	the jump table reloc.  Add an assertion.  Use RELOC_JMP_SLOT
	rather than the constant 22.
	(sunos_check_dynamic_reloc): Handle creating a shared library.
	(sunos_finish_dynamic_link): Set the first entry in the GOT to
	zero when creating a shared library.
	* aoutx.h (NAME(aout,final_link)): If there is a symbol __DYNAMIC,
	write it out at the start of the symbol table.
This commit is contained in:
Ian Lance Taylor 1995-09-28 16:30:54 +00:00
parent 11b072f46c
commit 9db5923077
2 changed files with 224 additions and 85 deletions

View File

@ -1,5 +1,23 @@
Thu Sep 28 11:19:53 1995 Ian Lance Taylor <ian@cygnus.com>
* sunos.c (sunos_add_one_symbol): Don't change
bfd_link_hash_common to bfd_link_hash_new, since it may be on the
undef list.
(bfd_sunos_record_link_assignment): Don't put __DYNAMIC in the
dynamic symbols when creating a shared library.
(sunos_scan_ext_relocs): Handle relocs correctly when creating a
shared library.
(sunos_scan_dynamic_symbol): Don't mark the __DYNAMIC symbol as
written even if it is not defined in a regular object.
(sunos_write_dynamic_symbol): Use plt_offset for the address of
the jump table reloc. Add an assertion. Use RELOC_JMP_SLOT
rather than the constant 22.
(sunos_check_dynamic_reloc): Handle creating a shared library.
(sunos_finish_dynamic_link): Set the first entry in the GOT to
zero when creating a shared library.
* aoutx.h (NAME(aout,final_link)): If there is a symbol __DYNAMIC,
write it out at the start of the symbol table.
* Makefile.in (BFD32_BACKENDS): Add coff-arm.o.
Thu Sep 28 00:58:05 1995 Doug Evans <dje@deneb.cygnus.com>

View File

@ -1008,18 +1008,25 @@ sunos_add_one_symbol (info, abfd, name, flags, section, value, string,
reference. */
section = bfd_und_section_ptr;
}
else if ((h->root.root.type == bfd_link_hash_defined
&& h->root.root.u.def.section->owner != NULL
&& (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0)
|| (h->root.root.type == bfd_link_hash_common
&& ((h->root.root.u.c.p->section->owner->flags & DYNAMIC)
!= 0)))
else if (h->root.root.type == bfd_link_hash_defined
&& h->root.root.u.def.section->owner != NULL
&& (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0)
{
/* The existing definition is from a dynamic object. We
want to override it with the definition we just found.
Clobber the existing definition. */
h->root.root.type = bfd_link_hash_new;
}
else if (h->root.root.type == bfd_link_hash_common
&& (h->root.root.u.c.p->section->owner->flags & DYNAMIC) != 0)
{
/* The existing definition is from a dynamic object. We
want to override it with the definition we just found.
Clobber the existing definition. We can't set it to new,
because it is on the undefined list. */
h->root.root.type = bfd_link_hash_undefined;
h->root.root.u.undef.abfd = h->root.root.u.c.p->section->owner;
}
}
/* Do the usual procedure for adding a symbol. */
@ -1081,12 +1088,17 @@ bfd_sunos_record_link_assignment (output_bfd, info, name)
if (h == NULL)
return true;
h->flags |= SUNOS_DEF_REGULAR;
if (h->dynindx == -1)
/* In a shared library, the __DYNAMIC symbol does not appear in the
dynamic symbol table. */
if (! info->shared || strcmp (name, "__DYNAMIC") != 0)
{
++sunos_hash_table (info)->dynsymcount;
h->dynindx = -2;
h->flags |= SUNOS_DEF_REGULAR;
if (h->dynindx == -1)
{
++sunos_hash_table (info)->dynsymcount;
h->dynindx = -2;
}
}
return true;
@ -1675,7 +1687,36 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
defined in dynamic objects but not in regular objects. We
only need to consider relocs against external symbols. */
if (! r_extern)
continue;
{
/* But, if we are creating a shared library, we need to
generate an absolute reloc. */
if (info->shared)
{
if (sec == obj_textsec (abfd))
{
(*_bfd_error_handler)
("%s: may not have .text section relocs in shared library",
bfd_get_filename (abfd));
bfd_set_error (bfd_error_nonrepresentable_section);
return false;
}
if (dynobj == NULL)
{
if (! sunos_create_dynamic_sections (abfd, info, true))
return false;
dynobj = sunos_hash_table (info)->dynobj;
splt = bfd_get_section_by_name (dynobj, ".plt");
sgot = bfd_get_section_by_name (dynobj, ".got");
srel = bfd_get_section_by_name (dynobj, ".dynrel");
BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
}
srel->_raw_size += RELOC_EXT_SIZE;
}
continue;
}
/* At this point common symbols have already been allocated, so
we don't have to worry about them. We need to consider that
@ -1688,6 +1729,7 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
continue;
if (r_type != RELOC_JMP_TBL
&& ! info->shared
&& ((h->flags & SUNOS_DEF_DYNAMIC) == 0
|| (h->flags & SUNOS_DEF_REGULAR) != 0))
continue;
@ -1709,6 +1751,7 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
BFD_ASSERT (r_type == RELOC_JMP_TBL
|| (h->flags & SUNOS_REF_REGULAR) != 0);
BFD_ASSERT (r_type == RELOC_JMP_TBL
|| info->shared
|| h->plt_offset != 0
|| ((h->root.root.type == bfd_link_hash_defined
|| h->root.root.type == bfd_link_hash_defweak)
@ -1719,24 +1762,28 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
/* This reloc is against a symbol defined only by a dynamic
object, or it is a jump table reloc from PIC compiled code. */
if (h->root.root.type == bfd_link_hash_undefined)
if (r_type != RELOC_JMP_TBL
&& h->root.root.type == bfd_link_hash_undefined)
{
/* Presumably this symbol was marked as being undefined by
an earlier reloc. */
srel->_raw_size += RELOC_EXT_SIZE;
}
else if ((h->root.root.u.def.section->flags & SEC_CODE) == 0)
else if (r_type != RELOC_JMP_TBL
&& (h->root.root.u.def.section->flags & SEC_CODE) == 0)
{
bfd *sub;
/* This reloc is not in the .text section. It must be
copied into the dynamic relocs. We mark the symbol as
being undefined. */
BFD_ASSERT (r_type != RELOC_JMP_TBL);
srel->_raw_size += RELOC_EXT_SIZE;
sub = h->root.root.u.def.section->owner;
h->root.root.type = bfd_link_hash_undefined;
h->root.root.u.undef.abfd = sub;
if ((h->flags & SUNOS_DEF_REGULAR) == 0)
{
sub = h->root.root.u.def.section->owner;
h->root.root.type = bfd_link_hash_undefined;
h->root.root.u.undef.abfd = sub;
}
}
else
{
@ -1753,6 +1800,8 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
if ((h->flags & SUNOS_DEF_REGULAR) == 0)
{
if (h->root.root.type == bfd_link_hash_undefined)
h->root.root.type = bfd_link_hash_defined;
h->root.root.u.def.section = splt;
h->root.root.u.def.value = splt->_raw_size;
}
@ -1765,6 +1814,11 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0)
srel->_raw_size += RELOC_EXT_SIZE;
}
/* If we are creating a shared library, we need to copy over
any reloc other than a jump table reloc. */
if (info->shared && r_type != RELOC_JMP_TBL)
srel->_raw_size += RELOC_EXT_SIZE;
}
}
@ -1786,7 +1840,8 @@ sunos_scan_dynamic_symbol (h, data)
not defined in a regular object file. For some reason symbols
which are referenced by a regular object and defined by a dynamic
object do not seem to show up in the regular symbol table. */
if ((h->flags & SUNOS_DEF_REGULAR) == 0)
if ((h->flags & SUNOS_DEF_REGULAR) == 0
&& strcmp (h->root.root.root.string, "__DYNAMIC") != 0)
h->root.written = true;
/* If this symbol is defined by a dynamic object and referenced by a
@ -2021,9 +2076,9 @@ sunos_write_dynamic_symbol (output_bfd, info, harg)
s = bfd_get_section_by_name (dynobj, ".dynrel");
r_address = (h->root.root.u.def.section->output_section->vma
+ h->root.root.u.def.section->output_offset
+ h->root.root.u.def.value);
r_address = (splt->output_section->vma
+ splt->output_offset
+ h->plt_offset);
switch (bfd_get_arch (output_bfd))
{
@ -2073,6 +2128,8 @@ sunos_write_dynamic_symbol (output_bfd, info, harg)
result of a JMP_TBL reloc from PIC compiled code. */
if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0)
{
BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj)
< s->_raw_size);
p = s->contents + s->reloc_count * obj_reloc_entry_size (output_bfd);
if (obj_reloc_entry_size (output_bfd) == RELOC_STD_SIZE)
{
@ -2108,16 +2165,18 @@ sunos_write_dynamic_symbol (output_bfd, info, harg)
erel->r_index[0] = h->dynindx >> 16;
erel->r_index[1] = h->dynindx >> 8;
erel->r_index[2] = h->dynindx;
erel->r_type[0] = (RELOC_EXT_BITS_EXTERN_BIG
| (22 << RELOC_EXT_BITS_TYPE_SH_BIG));
erel->r_type[0] =
(RELOC_EXT_BITS_EXTERN_BIG
| (RELOC_JMP_SLOT << RELOC_EXT_BITS_TYPE_SH_BIG));
}
else
{
erel->r_index[2] = h->dynindx >> 16;
erel->r_index[1] = h->dynindx >> 8;
erel->r_index[0] = h->dynindx;
erel->r_type[0] = (RELOC_EXT_BITS_EXTERN_LITTLE
| (22 << RELOC_EXT_BITS_TYPE_SH_LITTLE));
erel->r_type[0] =
(RELOC_EXT_BITS_EXTERN_LITTLE
| (RELOC_JMP_SLOT << RELOC_EXT_BITS_TYPE_SH_LITTLE));
}
PUT_WORD (output_bfd, (bfd_vma) 0, erel->r_addend);
}
@ -2150,8 +2209,10 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
struct sunos_link_hash_entry *h = (struct sunos_link_hash_entry *) harg;
bfd *dynobj;
boolean baserel;
boolean jmptbl;
asection *s;
bfd_byte *p;
long indx;
*skip = false;
@ -2174,9 +2235,15 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
srel = (struct reloc_std_external *) reloc;
if (input_bfd->xvec->header_byteorder_big_p)
baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
{
baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
jmptbl = (0 != (srel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG));
}
else
baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE));
{
baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE));
jmptbl = (0 != (srel->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
}
}
else
{
@ -2193,6 +2260,7 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
baserel = (r_type == RELOC_BASE10
|| r_type == RELOC_BASE13
|| r_type == RELOC_BASE22);
jmptbl = r_type == RELOC_JMP_TBL;
}
if (baserel)
@ -2247,21 +2315,35 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
already initialized the GOT entry. */
if ((*got_offsetp & 1) == 0)
{
PUT_WORD (dynobj, *relocationp, sgot->contents + *got_offsetp);
if (h == NULL
|| (! info->shared
&& ((h->flags & SUNOS_DEF_DYNAMIC) == 0
|| (h->flags & SUNOS_DEF_REGULAR) != 0)))
PUT_WORD (dynobj, *relocationp, sgot->contents + *got_offsetp);
else
PUT_WORD (dynobj, 0, sgot->contents + *got_offsetp);
if (h != NULL
&& (h->flags & SUNOS_DEF_DYNAMIC) != 0
&& (h->flags & SUNOS_DEF_REGULAR) == 0)
if (info->shared
|| (h != NULL
&& (h->flags & SUNOS_DEF_DYNAMIC) != 0
&& (h->flags & SUNOS_DEF_REGULAR) == 0))
{
/* We need to create a GLOB_DAT reloc to tell the
/* We need to create a GLOB_DAT or 32 reloc to tell the
dynamic linker to fill in this entry in the table. */
s = bfd_get_section_by_name (dynobj, ".dynrel");
BFD_ASSERT (s != NULL);
BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj)
< s->_raw_size);
p = (s->contents
+ s->reloc_count * obj_reloc_entry_size (dynobj));
if (h != NULL)
indx = h->dynindx;
else
indx = 0;
if (obj_reloc_entry_size (dynobj) == RELOC_STD_SIZE)
{
struct reloc_std_external *srel;
@ -2274,25 +2356,31 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
srel->r_address);
if (dynobj->xvec->header_byteorder_big_p)
{
srel->r_index[0] = h->dynindx >> 16;
srel->r_index[1] = h->dynindx >> 8;
srel->r_index[2] = h->dynindx;
srel->r_type[0] =
(RELOC_STD_BITS_EXTERN_BIG
| RELOC_STD_BITS_BASEREL_BIG
| RELOC_STD_BITS_RELATIVE_BIG
| (2 << RELOC_STD_BITS_LENGTH_SH_BIG));
srel->r_index[0] = indx >> 16;
srel->r_index[1] = indx >> 8;
srel->r_index[2] = indx;
if (h == NULL)
srel->r_type[0] = 2 << RELOC_STD_BITS_LENGTH_SH_BIG;
else
srel->r_type[0] =
(RELOC_STD_BITS_EXTERN_BIG
| RELOC_STD_BITS_BASEREL_BIG
| RELOC_STD_BITS_RELATIVE_BIG
| (2 << RELOC_STD_BITS_LENGTH_SH_BIG));
}
else
{
srel->r_index[2] = h->dynindx >> 16;
srel->r_index[1] = h->dynindx >> 8;
srel->r_index[0] = h->dynindx;
srel->r_type[0] =
(RELOC_STD_BITS_EXTERN_LITTLE
| RELOC_STD_BITS_BASEREL_LITTLE
| RELOC_STD_BITS_RELATIVE_LITTLE
| (2 << RELOC_STD_BITS_LENGTH_SH_LITTLE));
srel->r_index[2] = indx >> 16;
srel->r_index[1] = indx >> 8;
srel->r_index[0] = indx;
if (h == NULL)
srel->r_type[0] = 2 << RELOC_STD_BITS_LENGTH_SH_LITTLE;
else
srel->r_type[0] =
(RELOC_STD_BITS_EXTERN_LITTLE
| RELOC_STD_BITS_BASEREL_LITTLE
| RELOC_STD_BITS_RELATIVE_LITTLE
| (2 << RELOC_STD_BITS_LENGTH_SH_LITTLE));
}
}
else
@ -2307,21 +2395,30 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
erel->r_address);
if (dynobj->xvec->header_byteorder_big_p)
{
erel->r_index[0] = h->dynindx >> 16;
erel->r_index[1] = h->dynindx >> 8;
erel->r_index[2] = h->dynindx;
erel->r_type[0] =
(RELOC_EXT_BITS_EXTERN_BIG
| (RELOC_GLOB_DAT << RELOC_EXT_BITS_TYPE_SH_BIG));
erel->r_index[0] = indx >> 16;
erel->r_index[1] = indx >> 8;
erel->r_index[2] = indx;
if (h == NULL)
erel->r_type[0] =
RELOC_32 << RELOC_EXT_BITS_TYPE_SH_BIG;
else
erel->r_type[0] =
(RELOC_EXT_BITS_EXTERN_BIG
| (RELOC_GLOB_DAT << RELOC_EXT_BITS_TYPE_SH_BIG));
}
else
{
erel->r_index[2] = h->dynindx >> 16;
erel->r_index[1] = h->dynindx >> 8;
erel->r_index[0] = h->dynindx;
erel->r_type[0] =
(RELOC_EXT_BITS_EXTERN_LITTLE
| (RELOC_GLOB_DAT << RELOC_EXT_BITS_TYPE_SH_LITTLE));
erel->r_index[2] = indx >> 16;
erel->r_index[1] = indx >> 8;
erel->r_index[0] = indx;
if (h == NULL)
erel->r_type[0] =
RELOC_32 << RELOC_EXT_BITS_TYPE_SH_LITTLE;
else
erel->r_type[0] =
(RELOC_EXT_BITS_EXTERN_LITTLE
| (RELOC_GLOB_DAT
<< RELOC_EXT_BITS_TYPE_SH_LITTLE));
}
PUT_WORD (dynobj, 0, erel->r_addend);
}
@ -2338,25 +2435,45 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
return true;
}
if (! sunos_hash_table (info)->dynamic_sections_needed
|| h == NULL
|| h->dynindx == -1
|| h->root.root.type != bfd_link_hash_undefined
|| (h->flags & SUNOS_DEF_REGULAR) != 0
|| (h->flags & SUNOS_DEF_DYNAMIC) == 0
|| (h->root.root.u.undef.abfd->flags & DYNAMIC) == 0)
if (! sunos_hash_table (info)->dynamic_sections_needed)
return true;
if (! info->shared)
{
if (h == NULL
|| h->dynindx == -1
|| h->root.root.type != bfd_link_hash_undefined
|| (h->flags & SUNOS_DEF_REGULAR) != 0
|| (h->flags & SUNOS_DEF_DYNAMIC) == 0
|| (h->root.root.u.undef.abfd->flags & DYNAMIC) == 0)
return true;
}
else
{
if (h != NULL
&& (h->dynindx == -1
|| jmptbl
|| strcmp (h->root.root.root.string,
"__GLOBAL_OFFSET_TABLE_") == 0))
return true;
BFD_ASSERT (input_section != obj_textsec (input_bfd));
}
/* It looks like this is a reloc we are supposed to copy. */
s = bfd_get_section_by_name (dynobj, ".dynrel");
BFD_ASSERT (s != NULL);
BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj) < s->_raw_size);
p = s->contents + s->reloc_count * obj_reloc_entry_size (dynobj);
/* Copy the reloc over. */
memcpy (p, reloc, obj_reloc_entry_size (dynobj));
if (h != NULL)
indx = h->dynindx;
else
indx = 0;
/* Adjust the address and symbol index. */
if (obj_reloc_entry_size (dynobj) == RELOC_STD_SIZE)
{
@ -2370,15 +2487,15 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
srel->r_address);
if (dynobj->xvec->header_byteorder_big_p)
{
srel->r_index[0] = h->dynindx >> 16;
srel->r_index[1] = h->dynindx >> 8;
srel->r_index[2] = h->dynindx;
srel->r_index[0] = indx >> 16;
srel->r_index[1] = indx >> 8;
srel->r_index[2] = indx;
}
else
{
srel->r_index[2] = h->dynindx >> 16;
srel->r_index[1] = h->dynindx >> 8;
srel->r_index[0] = h->dynindx;
srel->r_index[2] = indx >> 16;
srel->r_index[1] = indx >> 8;
srel->r_index[0] = indx;
}
}
else
@ -2393,21 +2510,22 @@ sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
erel->r_address);
if (dynobj->xvec->header_byteorder_big_p)
{
erel->r_index[0] = h->dynindx >> 16;
erel->r_index[1] = h->dynindx >> 8;
erel->r_index[2] = h->dynindx;
erel->r_index[0] = indx >> 16;
erel->r_index[1] = indx >> 8;
erel->r_index[2] = indx;
}
else
{
erel->r_index[2] = h->dynindx >> 16;
erel->r_index[1] = h->dynindx >> 8;
erel->r_index[0] = h->dynindx;
erel->r_index[2] = indx >> 16;
erel->r_index[1] = indx >> 8;
erel->r_index[0] = indx;
}
}
++s->reloc_count;
*skip = true;
if (h != NULL)
*skip = true;
return true;
}
@ -2459,12 +2577,15 @@ sunos_finish_dynamic_link (abfd, info)
}
}
/* The first entry in the .got section is the address of the dynamic
information. */
/* The first entry in the .got section is the address of the
dynamic information, unless this is a shared library. */
s = bfd_get_section_by_name (dynobj, ".got");
BFD_ASSERT (s != NULL);
PUT_WORD (dynobj, sdyn->output_section->vma + sdyn->output_offset,
s->contents);
if (info->shared)
PUT_WORD (dynobj, 0, s->contents);
else
PUT_WORD (dynobj, sdyn->output_section->vma + sdyn->output_offset,
s->contents);
for (o = dynobj->sections; o != NULL; o = o->next)
{