aboutsummaryrefslogtreecommitdiff
path: root/bfd/sunos.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1995-09-28 16:30:54 +0000
committerIan Lance Taylor <ian@airs.com>1995-09-28 16:30:54 +0000
commit9db5923077da3e471b36b26ea17427e95ee7c67b (patch)
treee881159ee0775cbe27ae3d43f12e182c4d9fe79c /bfd/sunos.c
parent11b072f46c3c02c198a27b5abb0184778a2d0b73 (diff)
downloadgdb-9db5923077da3e471b36b26ea17427e95ee7c67b.zip
gdb-9db5923077da3e471b36b26ea17427e95ee7c67b.tar.gz
gdb-9db5923077da3e471b36b26ea17427e95ee7c67b.tar.bz2
* 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.
Diffstat (limited to 'bfd/sunos.c')
-rw-r--r--bfd/sunos.c291
1 files changed, 206 insertions, 85 deletions
diff --git a/bfd/sunos.c b/bfd/sunos.c
index f5e2bc8..f97a0a7 100644
--- a/bfd/sunos.c
+++ b/bfd/sunos.c
@@ -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)
{