aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1997-03-07 16:50:22 +0000
committerIan Lance Taylor <ian@airs.com>1997-03-07 16:50:22 +0000
commite8c4696e1b6dcf6a3d0e237cef3af77738d206fd (patch)
treebf823e901a7cbfe679bdf776555e7067ce941348 /bfd
parenta98a3061a6df939f64dbb01646780756a5e5dd22 (diff)
downloadgdb-e8c4696e1b6dcf6a3d0e237cef3af77738d206fd.zip
gdb-e8c4696e1b6dcf6a3d0e237cef3af77738d206fd.tar.gz
gdb-e8c4696e1b6dcf6a3d0e237cef3af77738d206fd.tar.bz2
* xcofflink.c (_bfd_xcoff_bfd_final_link): Always allocate space
for at least 6 output symbols. (xcoff_write_global_symbol): When emitting TOC entry relocs, also emit a TC csect to represent the space they take up. For an XO symbol, just emit a reference, not a csect. PR 11793.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog6
-rw-r--r--bfd/xcofflink.c251
2 files changed, 215 insertions, 42 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 1707386..a06fe34 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,11 @@
Fri Mar 7 10:37:30 1997 Ian Lance Taylor <ian@cygnus.com>
+ * xcofflink.c (_bfd_xcoff_bfd_final_link): Always allocate space
+ for at least 6 output symbols.
+ (xcoff_write_global_symbol): When emitting TOC entry relocs, also
+ emit a TC csect to represent the space they take up. For an XO
+ symbol, just emit a reference, not a csect.
+
* Makefile.in ($(SHLINK)): Just use ln -s, not ln -sf, since
Solaris doesn't like the combined options, and the -f is
unnecessary.
diff --git a/bfd/xcofflink.c b/bfd/xcofflink.c
index 3892f17..64cc0f8 100644
--- a/bfd/xcofflink.c
+++ b/bfd/xcofflink.c
@@ -1,5 +1,5 @@
/* POWER/PowerPC XCOFF linker support.
- Copyright 1995, 1996 Free Software Foundation, Inc.
+ Copyright 1995, 1996, 1997 Free Software Foundation, Inc.
Written by Ian Lance Taylor <ian@cygnus.com>, Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
@@ -269,7 +269,9 @@ struct xcoff_link_hash_entry
/* The .loader symbol table entry, if there is one. */
struct internal_ldsym *ldsym;
- /* The .loader symbol table index. */
+ /* If XCOFF_BUILT_LDSYM is set, this is the .loader symbol table
+ index. If XCOFF_BUILD_LDSYM is clear, and XCOFF_IMPORT is set,
+ this is the l_ifile value. */
long ldindx;
/* Some linker flags. */
@@ -1408,6 +1410,8 @@ xcoff_link_add_symbols (abfd, info)
bfd_byte *linenos;
} *reloc_info = NULL;
+ keep_syms = obj_coff_keep_syms (abfd);
+
if ((abfd->flags & DYNAMIC) != 0
&& ! info->static_link)
{
@@ -1571,7 +1575,6 @@ xcoff_link_add_symbols (abfd, info)
}
/* Don't let the linker relocation routines discard the symbols. */
- keep_syms = obj_coff_keep_syms (abfd);
obj_coff_keep_syms (abfd) = true;
csect = NULL;
@@ -2560,6 +2563,61 @@ xcoff_link_add_dynamic_symbols (abfd, info)
h->root.u.def.section = bfd_abs_section_ptr;
h->root.u.def.value = ldsym.l_value;
}
+
+ /* If this symbol defines a function descriptor, then it
+ implicitly defines the function code as well. */
+ if (h->smclas == XMC_DS
+ || (h->smclas == XMC_XO && name[0] != '.'))
+ h->flags |= XCOFF_DESCRIPTOR;
+ if ((h->flags & XCOFF_DESCRIPTOR) != 0)
+ {
+ struct xcoff_link_hash_entry *hds;
+
+ hds = h->descriptor;
+ if (hds == NULL)
+ {
+ char *dsnm;
+
+ dsnm = bfd_malloc (strlen (name) + 2);
+ if (dsnm == NULL)
+ return false;
+ dsnm[0] = '.';
+ strcpy (dsnm + 1, name);
+ hds = xcoff_link_hash_lookup (xcoff_hash_table (info), dsnm,
+ true, true, true);
+ free (dsnm);
+ if (hds == NULL)
+ return false;
+
+ if (hds->root.type == bfd_link_hash_new)
+ {
+ hds->root.type = bfd_link_hash_undefined;
+ hds->root.u.undef.abfd = abfd;
+ /* We do not want to add this to the undefined
+ symbol list. */
+ }
+
+ hds->descriptor = h;
+ h->descriptor = hds;
+ }
+
+ hds->flags |= XCOFF_DEF_DYNAMIC;
+ if (hds->smclas == XMC_UA)
+ hds->smclas = XMC_PR;
+
+ /* An absolute symbol appears to actually define code, not a
+ function descriptor. This is how some math functions are
+ implemented on AIX 4.1. */
+ if (h->smclas == XMC_XO
+ && (hds->root.type == bfd_link_hash_undefined
+ || hds->root.type == bfd_link_hash_undefweak))
+ {
+ hds->smclas = XMC_XO;
+ hds->root.type = bfd_link_hash_defined;
+ hds->root.u.def.section = bfd_abs_section_ptr;
+ hds->root.u.def.value = ldsym.l_value;
+ }
+ }
}
if (buf != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
@@ -2740,7 +2798,6 @@ xcoff_mark (info, sec)
&& h->root.root.string[0] == '.'
&& h->descriptor != NULL
&& ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0
- || info->shared
|| ((h->descriptor->flags & XCOFF_IMPORT) != 0
&& (h->descriptor->flags
& XCOFF_DEF_REGULAR) == 0))))
@@ -2890,16 +2947,12 @@ bfd_xcoff_import_symbol (output_bfd, info, harg, val, imppath, impfile,
h->root.u.def.value = val;
}
- if (h->ldsym == NULL)
- {
- h->ldsym = ((struct internal_ldsym *)
- bfd_zalloc (output_bfd, sizeof (struct internal_ldsym)));
- if (h->ldsym == NULL)
- return false;
- }
-
+ /* We overload the ldindx field to hold the l_ifile value for this
+ symbol. */
+ BFD_ASSERT (h->ldsym == NULL);
+ BFD_ASSERT ((h->flags & XCOFF_BUILT_LDSYM) == 0);
if (imppath == NULL)
- h->ldsym->l_ifile = (bfd_size_type) -1;
+ h->ldindx = -1;
else
{
unsigned int c;
@@ -2932,7 +2985,7 @@ bfd_xcoff_import_symbol (output_bfd, info, harg, val, imppath, impfile,
*pp = n;
}
- h->ldsym->l_ifile = c;
+ h->ldindx = c;
}
return true;
@@ -3466,7 +3519,47 @@ xcoff_build_ldsyms (h, p)
if (ldinfo->export_defineds
&& (h->flags & XCOFF_DEF_REGULAR) != 0
&& h->root.root.string[0] != '.')
- h->flags |= XCOFF_EXPORT;
+ {
+ boolean export;
+
+ /* We don't export a symbol which is being defined by an object
+ included from an archive which contains a shared object. The
+ rationale is that if an archive contains both an unshared and
+ a shared object, then there must be some reason that the
+ unshared object is unshared, and we don't want to start
+ providing a shared version of it. In particular, this solves
+ a bug involving the _savefNN set of functions. gcc will call
+ those functions without providing a slot to restore the TOC,
+ so it is essential that these functions be linked in directly
+ and not from a shared object, which means that a shared
+ object which also happens to link them in must not export
+ them. This is confusing, but I haven't been able to think of
+ a different approach. Note that the symbols can, of course,
+ be exported explicitly. */
+ export = true;
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && h->root.u.def.section->owner != NULL
+ && h->root.u.def.section->owner->my_archive != NULL)
+ {
+ bfd *arbfd, *member;
+
+ arbfd = h->root.u.def.section->owner->my_archive;
+ member = bfd_openr_next_archived_file (arbfd, (bfd *) NULL);
+ while (member != NULL)
+ {
+ if ((member->flags & DYNAMIC) != 0)
+ {
+ export = false;
+ break;
+ }
+ member = bfd_openr_next_archived_file (arbfd, member);
+ }
+ }
+
+ if (export)
+ h->flags |= XCOFF_EXPORT;
+ }
/* We don't want to garbage collect symbols which are not defined in
XCOFF files. This is a convenient place to mark them. */
@@ -3479,17 +3572,16 @@ xcoff_build_ldsyms (h, p)
!= ldinfo->info->hash->creator)))
h->flags |= XCOFF_MARK;
- /* If this symbol is called and defined in a dynamic object, or not
- defined at all when building a shared object, or imported, then
- we need to set up global linkage code for it. (Unless we did
- garbage collection and we didn't need this symbol.) */
+ /* If this symbol is called and defined in a dynamic object, or it
+ is imported, then we need to set up global linkage code for it.
+ (Unless we did garbage collection and we didn't need this
+ symbol.) */
if ((h->flags & XCOFF_CALLED) != 0
&& (h->root.type == bfd_link_hash_undefined
|| h->root.type == bfd_link_hash_undefweak)
&& h->root.root.string[0] == '.'
&& h->descriptor != NULL
&& ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0
- || ldinfo->info->shared
|| ((h->descriptor->flags & XCOFF_IMPORT) != 0
&& (h->descriptor->flags & XCOFF_DEF_REGULAR) == 0))
&& (! xcoff_hash_table (ldinfo->info)->gc
@@ -3619,20 +3711,19 @@ xcoff_build_ldsyms (h, p)
/* We need to add this symbol to the .loader symbols. */
- /* h->ldsym will already have been allocated for an explicitly
- imported symbol. */
+ BFD_ASSERT (h->ldsym == NULL);
+ h->ldsym = ((struct internal_ldsym *)
+ bfd_zalloc (ldinfo->output_bfd,
+ sizeof (struct internal_ldsym)));
if (h->ldsym == NULL)
{
- h->ldsym = ((struct internal_ldsym *)
- bfd_zalloc (ldinfo->output_bfd,
- sizeof (struct internal_ldsym)));
- if (h->ldsym == NULL)
- {
- ldinfo->failed = true;
- return false;
- }
+ ldinfo->failed = true;
+ return false;
}
+ if ((h->flags & XCOFF_IMPORT) != 0)
+ h->ldsym->l_ifile = h->ldindx;
+
/* The first 3 symbol table indices are reserved to indicate the
sections. */
h->ldindx = ldinfo->ldsym_count + 3;
@@ -3807,7 +3898,6 @@ _bfd_xcoff_bfd_final_link (abfd, info)
saw_contents = true;
for (op = &abfd->sections; *op != NULL; op = &(*op)->next)
{
- (*op)->target_index = indx;
if (strcmp ((*op)->name, ".pad") == 0)
saw_contents = false;
else if (((*op)->flags & SEC_HAS_CONTENTS) != 0
@@ -3967,9 +4057,9 @@ _bfd_xcoff_bfd_final_link (abfd, info)
/* Figure out the largest number of symbols in an input BFD. Take
the opportunity to clear the output_has_begun fields of all the
- input BFD's. We want at least 4 symbols, since that is the
+ input BFD's. We want at least 6 symbols, since that is the
number which xcoff_write_global_symbol may need. */
- max_sym_count = 4;
+ max_sym_count = 6;
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
{
size_t sz;
@@ -4617,8 +4707,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
&& (isym.n_sclass != C_EXT
&& (isym.n_sclass != C_HIDEXT
|| smtyp != XTY_SD))
- && strncmp (name, finfo->info->lprefix,
- finfo->info->lprefix_len) == 0))
+ && bfd_is_local_label_name (input_bfd, name)))
skip = true;
}
@@ -5455,6 +5544,7 @@ xcoff_write_global_symbol (h, p)
union internal_auxent aux;
output_bfd = finfo->output_bfd;
+ outsym = finfo->outsyms;
/* If this symbol was garbage collected, just skip it. */
if (xcoff_hash_table (finfo->info)->gc
@@ -5563,6 +5653,8 @@ xcoff_write_global_symbol (h, p)
int oindx;
struct internal_reloc *irel;
struct internal_ldrel ldrel;
+ struct internal_syment irsym;
+ union internal_auxent iraux;
tocsec = h->toc_section;
osec = tocsec->output_section;
@@ -5590,6 +5682,63 @@ xcoff_write_global_symbol (h, p)
ldrel.l_rsecnm = oindx;
xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
++finfo->ldrel;
+
+ /* We need to emit a symbol to define a csect which holds the
+ reloc. */
+ if (strlen (h->root.root.string) <= SYMNMLEN)
+ strncpy (irsym._n._n_name, h->root.root.string, SYMNMLEN);
+ else
+ {
+ boolean hash;
+ bfd_size_type indx;
+
+ hash = true;
+ if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
+ hash = false;
+ indx = _bfd_stringtab_add (finfo->strtab, h->root.root.string, hash,
+ false);
+ if (indx == (bfd_size_type) -1)
+ return false;
+ irsym._n._n_n._n_zeroes = 0;
+ irsym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
+ }
+
+ irsym.n_value = irel->r_vaddr;
+ irsym.n_scnum = osec->target_index;
+ irsym.n_sclass = C_HIDEXT;
+ irsym.n_type = T_NULL;
+ irsym.n_numaux = 1;
+
+ bfd_coff_swap_sym_out (output_bfd, (PTR) &irsym, (PTR) outsym);
+ outsym += bfd_coff_symesz (output_bfd);
+
+ memset (&iraux, 0, sizeof iraux);
+ iraux.x_csect.x_smtyp = XTY_SD;
+ iraux.x_csect.x_scnlen.l = 4;
+ iraux.x_csect.x_smclas = XMC_TC;
+
+ bfd_coff_swap_aux_out (output_bfd, (PTR) &iraux, T_NULL, C_HIDEXT, 0, 1,
+ (PTR) outsym);
+ outsym += bfd_coff_auxesz (output_bfd);
+
+ if (h->indx >= 0)
+ {
+ /* We aren't going to write out the symbols below, so we
+ need to write them out now. */
+ if (bfd_seek (output_bfd,
+ (obj_sym_filepos (output_bfd)
+ + (obj_raw_syment_count (output_bfd)
+ * bfd_coff_symesz (output_bfd))),
+ SEEK_SET) != 0
+ || (bfd_write (finfo->outsyms, outsym - finfo->outsyms, 1,
+ output_bfd)
+ != (bfd_size_type) (outsym - finfo->outsyms)))
+ return false;
+ obj_raw_syment_count (output_bfd) +=
+ (outsym - finfo->outsyms) / bfd_coff_symesz (output_bfd);
+
+ outsym = finfo->outsyms;
+ }
}
/* If this symbol is a specially defined function descriptor, write
@@ -5697,7 +5846,10 @@ xcoff_write_global_symbol (h, p)
}
if (h->indx >= 0)
- return true;
+ {
+ BFD_ASSERT (outsym == finfo->outsyms);
+ return true;
+ }
if (h->indx != -2
&& (finfo->info->strip == strip_all
@@ -5705,13 +5857,17 @@ xcoff_write_global_symbol (h, p)
&& (bfd_hash_lookup (finfo->info->keep_hash,
h->root.root.string, false, false)
== NULL))))
- return true;
+ {
+ BFD_ASSERT (outsym == finfo->outsyms);
+ return true;
+ }
if (h->indx != -2
&& (h->flags & (XCOFF_REF_REGULAR | XCOFF_DEF_REGULAR)) == 0)
- return true;
-
- outsym = finfo->outsyms;
+ {
+ BFD_ASSERT (outsym == finfo->outsyms);
+ return true;
+ }
memset (&aux, 0, sizeof aux);
@@ -5743,6 +5899,16 @@ xcoff_write_global_symbol (h, p)
isym.n_sclass = C_EXT;
aux.x_csect.x_smtyp = XTY_ER;
}
+ else if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && h->smclas == XMC_XO)
+ {
+ BFD_ASSERT (bfd_is_abs_section (h->root.u.def.section));
+ isym.n_value = h->root.u.def.value;
+ isym.n_scnum = N_UNDEF;
+ isym.n_sclass = C_EXT;
+ aux.x_csect.x_smtyp = XTY_ER;
+ }
else if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
@@ -5793,8 +5959,9 @@ xcoff_write_global_symbol (h, p)
(PTR) outsym);
outsym += bfd_coff_auxesz (output_bfd);
- if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && h->smclas != XMC_XO)
{
/* We just output an SD symbol. Now output an LD symbol. */