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. */
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;
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
continue;
if (r_type != RELOC_JMP_TBL
+ && ! info->shared
&& ((h->flags & SUNOS_DEF_DYNAMIC) == 0
|| (h->flags & SUNOS_DEF_REGULAR) != 0))
continue;
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)
/* 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
{
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;
}
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;
}
}
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
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))
{
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)
{
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);
}
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;
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
{
baserel = (r_type == RELOC_BASE10
|| r_type == RELOC_BASE13
|| r_type == RELOC_BASE22);
+ jmptbl = r_type == RELOC_JMP_TBL;
}
if (baserel)
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;
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
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);
}
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)
{
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
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;
}
}
}
- /* 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)
{