mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-12-12 06:26:17 +00:00
* 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.
This commit is contained in:
parent
a98a3061a6
commit
e8c4696e1b
@ -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.
|
||||
|
251
bfd/xcofflink.c
251
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. */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user