* linker.c (_bfd_generic_link_add_one_symbol): If hashp and *hashp

are not NULL, assume the caller has already looked up the symbol
	in the hash table and has stored the entry in *hashp.
	(generic_link_add_symbol_list): Set h to NULL before calling
	_bfd_generic_link_add_one_symbol.
	* ecoff.c (ecoff_link_add_externals): Likewise.
This commit is contained in:
Ian Lance Taylor
1994-05-09 23:22:00 +00:00
parent 580937986f
commit 8e5090ce3a
3 changed files with 195 additions and 189 deletions

View File

@ -1,5 +1,15 @@
Mon May 9 11:53:54 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) Mon May 9 11:53:54 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
* linker.c (_bfd_generic_link_add_one_symbol): If hashp and *hashp
are not NULL, assume the caller has already looked up the symbol
in the hash table and has stored the entry in *hashp.
(generic_link_add_symbol_list): Set h to NULL before calling
_bfd_generic_link_add_one_symbol.
* ecoff.c (ecoff_link_add_externals): Likewise.
* elfcode.h (assign_file_positions_except_relocs): Don't require
page shared between .data and .bss segments to contain zeroes.
* elfcode.h: Include bfdlink.h. Added several new functions to do * elfcode.h: Include bfdlink.h. Added several new functions to do
linking. linking.
(ELF_R_TYPE): Define. (ELF_R_TYPE): Define.

View File

@ -99,7 +99,6 @@ ecoff_mkobject_hook (abfd, filehdr, aouthdr)
struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr; struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
struct internal_aouthdr *internal_a = (struct internal_aouthdr *) aouthdr; struct internal_aouthdr *internal_a = (struct internal_aouthdr *) aouthdr;
ecoff_data_type *ecoff; ecoff_data_type *ecoff;
asection *regsec;
if (ecoff_mkobject (abfd) == false) if (ecoff_mkobject (abfd) == false)
return NULL; return NULL;
@ -108,13 +107,6 @@ ecoff_mkobject_hook (abfd, filehdr, aouthdr)
ecoff->gp_size = 8; ecoff->gp_size = 8;
ecoff->sym_filepos = internal_f->f_symptr; ecoff->sym_filepos = internal_f->f_symptr;
/* Create the .reginfo section to give programs outside BFD a way to
see the information stored in the a.out header. See the comment
in coff/ecoff.h. */
regsec = bfd_make_section (abfd, REGINFO);
if (regsec == NULL)
return NULL;
if (internal_a != (struct internal_aouthdr *) NULL) if (internal_a != (struct internal_aouthdr *) NULL)
{ {
int i; int i;
@ -184,15 +176,6 @@ ecoff_new_section_hook (abfd, section)
/* An Irix 4 shared libary. */ /* An Irix 4 shared libary. */
section->flags |= SEC_SHARED_LIBRARY; section->flags |= SEC_SHARED_LIBRARY;
} }
else if (strcmp (section->name, REGINFO) == 0)
{
/* Setting SEC_SHARED_LIBRARY should make the linker leave the
section completely alone. */
section->flags |= (SEC_SHARED_LIBRARY
| SEC_HAS_CONTENTS
| SEC_NEVER_LOAD);
section->_raw_size = sizeof (struct ecoff_reginfo);
}
/* Probably any other section name is SEC_NEVER_LOAD, but I'm /* Probably any other section name is SEC_NEVER_LOAD, but I'm
uncertain about .init on some systems and I don't know how shared uncertain about .init on some systems and I don't know how shared
@ -2187,12 +2170,21 @@ ecoff_bfd_copy_private_bfd_data (ibfd, obfd)
{ {
struct ecoff_debug_info *iinfo = &ecoff_data (ibfd)->debug_info; struct ecoff_debug_info *iinfo = &ecoff_data (ibfd)->debug_info;
struct ecoff_debug_info *oinfo = &ecoff_data (obfd)->debug_info; struct ecoff_debug_info *oinfo = &ecoff_data (obfd)->debug_info;
register int i;
asymbol **sym_ptr_ptr; asymbol **sym_ptr_ptr;
size_t c; size_t c;
boolean local; boolean local;
BFD_ASSERT (ibfd->xvec == obfd->xvec); BFD_ASSERT (ibfd->xvec == obfd->xvec);
/* Copy the GP value and the register masks. */
ecoff_data (obfd)->gp = ecoff_data (ibfd)->gp;
ecoff_data (obfd)->gprmask = ecoff_data (ibfd)->gprmask;
ecoff_data (obfd)->fprmask = ecoff_data (ibfd)->fprmask;
for (i = 0; i < 3; i++)
ecoff_data (obfd)->cprmask[i] = ecoff_data (ibfd)->cprmask[i];
/* Copy the version stamp. */
oinfo->symbolic_header.vstamp = iinfo->symbolic_header.vstamp; oinfo->symbolic_header.vstamp = iinfo->symbolic_header.vstamp;
/* If there are no symbols, don't copy any debugging information. */ /* If there are no symbols, don't copy any debugging information. */
@ -2287,8 +2279,7 @@ ecoff_set_arch_mach (abfd, arch, machine)
return arch == ecoff_backend (abfd)->arch; return arch == ecoff_backend (abfd)->arch;
} }
/* Get the size of the section headers. We do not output the .reginfo /* Get the size of the section headers. */
section. */
/*ARGSUSED*/ /*ARGSUSED*/
int int
@ -2304,8 +2295,7 @@ ecoff_sizeof_headers (abfd, reloc)
for (current = abfd->sections; for (current = abfd->sections;
current != (asection *)NULL; current != (asection *)NULL;
current = current->next) current = current->next)
if (strcmp (current->name, REGINFO) != 0) ++c;
++c;
ret = (bfd_coff_filhsz (abfd) ret = (bfd_coff_filhsz (abfd)
+ bfd_coff_aoutsz (abfd) + bfd_coff_aoutsz (abfd)
@ -2313,9 +2303,7 @@ ecoff_sizeof_headers (abfd, reloc)
return BFD_ALIGN (ret, 16); return BFD_ALIGN (ret, 16);
} }
/* Get the contents of a section. This is where we handle reading the /* Get the contents of a section. */
.reginfo section, which implicitly holds the contents of an
ecoff_reginfo structure. */
boolean boolean
ecoff_get_section_contents (abfd, section, location, offset, count) ecoff_get_section_contents (abfd, section, location, offset, count)
@ -2325,26 +2313,8 @@ ecoff_get_section_contents (abfd, section, location, offset, count)
file_ptr offset; file_ptr offset;
bfd_size_type count; bfd_size_type count;
{ {
ecoff_data_type *tdata = ecoff_data (abfd); return _bfd_generic_get_section_contents (abfd, section, location,
struct ecoff_reginfo s; offset, count);
int i;
if (strcmp (section->name, REGINFO) != 0)
return _bfd_generic_get_section_contents (abfd, section, location,
offset, count);
s.gp_value = tdata->gp;
s.gprmask = tdata->gprmask;
for (i = 0; i < 4; i++)
s.cprmask[i] = tdata->cprmask[i];
s.fprmask = tdata->fprmask;
/* bfd_get_section_contents has already checked that the offset and
size is reasonable. We don't have to worry about swapping or any
such thing; the .reginfo section is defined such that the
contents are an ecoff_reginfo structure as seen on the host. */
memcpy (location, ((char *) &s) + offset, (size_t) count);
return true;
} }
/* Calculate the file position for each section, and set /* Calculate the file position for each section, and set
@ -2369,8 +2339,7 @@ ecoff_compute_section_file_positions (abfd)
unsigned int alignment_power; unsigned int alignment_power;
/* Only deal with sections which have contents */ /* Only deal with sections which have contents */
if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0 if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0)
|| strcmp (current->name, REGINFO) == 0)
continue; continue;
/* For the Alpha ECOFF .pdata section the lnnoptr field is /* For the Alpha ECOFF .pdata section the lnnoptr field is
@ -2460,8 +2429,6 @@ ecoff_compute_reloc_file_positions (abfd)
current != (asection *)NULL; current != (asection *)NULL;
current = current->next) current = current->next)
{ {
if (strcmp (current->name, REGINFO) == 0)
continue;
if (current->reloc_count == 0) if (current->reloc_count == 0)
current->rel_filepos = 0; current->rel_filepos = 0;
else else
@ -2490,9 +2457,7 @@ ecoff_compute_reloc_file_positions (abfd)
return reloc_size; return reloc_size;
} }
/* Set the contents of a section. This is where we handle setting the /* Set the contents of a section. */
contents of the .reginfo section, which implicitly holds a
ecoff_reginfo structure. */
boolean boolean
ecoff_set_section_contents (abfd, section, location, offset, count) ecoff_set_section_contents (abfd, section, location, offset, count)
@ -2516,39 +2481,6 @@ ecoff_set_section_contents (abfd, section, location, offset, count)
if (count == 0) if (count == 0)
return true; return true;
if (strcmp (section->name, REGINFO) == 0)
{
ecoff_data_type *tdata = ecoff_data (abfd);
struct ecoff_reginfo s;
int i;
/* If the caller is only changing part of the structure, we must
retrieve the current information before the memcpy. */
if (offset != 0 || count != sizeof (struct ecoff_reginfo))
{
s.gp_value = tdata->gp;
s.gprmask = tdata->gprmask;
for (i = 0; i < 4; i++)
s.cprmask[i] = tdata->cprmask[i];
s.fprmask = tdata->fprmask;
}
/* bfd_set_section_contents has already checked that the offset
and size is reasonable. We don't have to worry about
swapping or any such thing; the .reginfo section is defined
such that the contents are an ecoff_reginfo structure as seen
on the host. */
memcpy (((char *) &s) + offset, location, (size_t) count);
tdata->gp = s.gp_value;
tdata->gprmask = s.gprmask;
for (i = 0; i < 4; i++)
tdata->cprmask[i] = s.cprmask[i];
tdata->fprmask = s.fprmask;
return true;
}
if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0 if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
|| bfd_write (location, 1, count, abfd) != count) || bfd_write (location, 1, count, abfd) != count)
return false; return false;
@ -2556,6 +2488,76 @@ ecoff_set_section_contents (abfd, section, location, offset, count)
return true; return true;
} }
/* Get the GP value for an ECOFF file. This is a hook used by
nlmconv. */
bfd_vma
bfd_ecoff_get_gp_value (abfd)
bfd *abfd;
{
if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
|| bfd_get_format (abfd) != bfd_object)
{
bfd_set_error (bfd_error_invalid_operation);
return 0;
}
return ecoff_data (abfd)->gp;
}
/* Set the GP value for an ECOFF file. This is a hook used by the
assembler. */
boolean
bfd_ecoff_set_gp_value (abfd, gp_value)
bfd *abfd;
bfd_vma gp_value;
{
if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
|| bfd_get_format (abfd) != bfd_object)
{
bfd_set_error (bfd_error_invalid_operation);
return false;
}
ecoff_data (abfd)->gp = gp_value;
return true;
}
/* Set the register masks for an ECOFF file. This is a hook used by
the assembler. */
boolean
bfd_ecoff_set_regmasks (abfd, gprmask, fprmask, cprmask)
bfd *abfd;
unsigned long gprmask;
unsigned long fprmask;
unsigned long *cprmask;
{
ecoff_data_type *tdata;
if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
|| bfd_get_format (abfd) != bfd_object)
{
bfd_set_error (bfd_error_invalid_operation);
return false;
}
tdata = ecoff_data (abfd);
tdata->gprmask = gprmask;
tdata->fprmask = fprmask;
if (cprmask != (unsigned long *) NULL)
{
register int i;
for (i = 0; i < 3; i++)
tdata->cprmask[i] = cprmask[i];
}
return true;
}
/* Get ECOFF EXTR information for an external symbol. This function /* Get ECOFF EXTR information for an external symbol. This function
is passed to bfd_ecoff_debug_externals. */ is passed to bfd_ecoff_debug_externals. */
@ -2681,8 +2683,6 @@ ecoff_write_object_contents (abfd)
current != (asection *)NULL; current != (asection *)NULL;
current = current->next) current = current->next)
{ {
if (strcmp (current->name, REGINFO) == 0)
continue;
current->target_index = count; current->target_index = count;
++count; ++count;
} }
@ -2727,12 +2727,6 @@ ecoff_write_object_contents (abfd)
struct internal_scnhdr section; struct internal_scnhdr section;
bfd_vma vma; bfd_vma vma;
if (strcmp (current->name, REGINFO) == 0)
{
BFD_ASSERT (current->reloc_count == 0);
continue;
}
++internal_f.f_nscns; ++internal_f.f_nscns;
strncpy (section.s_name, current->name, sizeof section.s_name); strncpy (section.s_name, current->name, sizeof section.s_name);
@ -4150,6 +4144,7 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
name = ssext + esym.asym.iss; name = ssext + esym.asym.iss;
h = NULL;
if (! (_bfd_generic_link_add_one_symbol if (! (_bfd_generic_link_add_one_symbol
(info, abfd, name, BSF_GLOBAL, section, value, (info, abfd, name, BSF_GLOBAL, section, value,
(const char *) NULL, true, true, (const char *) NULL, true, true,
@ -4359,11 +4354,6 @@ ecoff_bfd_final_link (abfd, info)
for (o = abfd->sections; o != (asection *) NULL; o = o->next) for (o = abfd->sections; o != (asection *) NULL; o = o->next)
{ {
/* Ignore any link_orders for the .reginfo section, which does
not really exist. */
if (strcmp (o->name, REGINFO) == 0)
continue;
for (p = o->link_order_head; for (p = o->link_order_head;
p != (struct bfd_link_order *) NULL; p != (struct bfd_link_order *) NULL;
p = p->next) p = p->next)

View File

@ -412,6 +412,8 @@ SUBSUBSECTION
static struct bfd_hash_entry *generic_link_hash_newfunc static struct bfd_hash_entry *generic_link_hash_newfunc
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
const char *)); const char *));
static boolean generic_link_read_symbols
PARAMS ((bfd *));
static boolean generic_link_add_symbols static boolean generic_link_add_symbols
PARAMS ((bfd *, struct bfd_link_info *, boolean collect)); PARAMS ((bfd *, struct bfd_link_info *, boolean collect));
static boolean generic_link_add_object_symbols static boolean generic_link_add_object_symbols
@ -610,6 +612,40 @@ _bfd_generic_link_hash_table_create (abfd)
} }
return &ret->root; return &ret->root;
} }
/* Grab the symbols for an object file when doing a generic link. We
store the symbols in the outsymbols field. We need to keep them
around for the entire link to ensure that we only read them once.
If we read them multiple times, we might wind up with relocs and
the hash table pointing to different instances of the symbol
structure. */
static boolean
generic_link_read_symbols (abfd)
bfd *abfd;
{
if (abfd->outsymbols == (asymbol **) NULL)
{
long symsize;
long symcount;
symsize = bfd_get_symtab_upper_bound (abfd);
if (symsize < 0)
return false;
abfd->outsymbols = (asymbol **) bfd_alloc (abfd, symsize);
if (abfd->outsymbols == NULL && symsize != 0)
{
bfd_set_error (bfd_error_no_memory);
return false;
}
symcount = bfd_canonicalize_symtab (abfd, abfd->outsymbols);
if (symcount < 0)
return false;
abfd->symcount = symcount;
}
return true;
}
/* Generic function to add symbols to from an object file to the /* Generic function to add symbols to from an object file to the
global hash table. This version does not automatically collect global hash table. This version does not automatically collect
@ -676,24 +712,12 @@ generic_link_add_object_symbols (abfd, info, collect)
struct bfd_link_info *info; struct bfd_link_info *info;
boolean collect; boolean collect;
{ {
size_t symsize; if (! generic_link_read_symbols (abfd))
asymbol **symbols; return false;
bfd_size_type symbol_count; return generic_link_add_symbol_list (abfd, info,
boolean result; _bfd_generic_link_get_symcount (abfd),
_bfd_generic_link_get_symbols (abfd),
symsize = get_symtab_upper_bound (abfd); collect);
symbols = (asymbol **) malloc (symsize);
if (symbols == NULL && symsize != 0)
{
bfd_set_error (bfd_error_no_memory);
return false;
}
symbol_count = bfd_canonicalize_symtab (abfd, symbols);
result = generic_link_add_symbol_list (abfd, info, symbol_count, symbols,
collect);
free (symbols);
return result;
} }
/* We build a hash table of all symbols defined in an archive. */ /* We build a hash table of all symbols defined in an archive. */
@ -1005,25 +1029,15 @@ generic_link_check_archive_element (abfd, info, pneeded, collect)
boolean *pneeded; boolean *pneeded;
boolean collect; boolean collect;
{ {
size_t symsize;
asymbol **symbols = NULL;
bfd_size_type symbol_count;
asymbol **pp, **ppend; asymbol **pp, **ppend;
*pneeded = false; *pneeded = false;
symsize = get_symtab_upper_bound (abfd); if (! generic_link_read_symbols (abfd))
symbols = (asymbol **) malloc (symsize); return false;
if (symbols == NULL && symsize != 0)
{
bfd_set_error (bfd_error_no_memory);
goto error_return;
}
symbol_count = bfd_canonicalize_symtab (abfd, symbols); pp = _bfd_generic_link_get_symbols (abfd);
ppend = pp + _bfd_generic_link_get_symcount (abfd);
pp = symbols;
ppend = symbols + symbol_count;
for (; pp < ppend; pp++) for (; pp < ppend; pp++)
{ {
asymbol *p; asymbol *p;
@ -1052,15 +1066,20 @@ generic_link_check_archive_element (abfd, info, pneeded, collect)
if (! bfd_is_com_section (p->section)) if (! bfd_is_com_section (p->section))
{ {
bfd_size_type symcount;
asymbol **symbols;
/* This object file defines this symbol, so pull it in. */ /* This object file defines this symbol, so pull it in. */
if (! (*info->callbacks->add_archive_element) (info, abfd, if (! (*info->callbacks->add_archive_element) (info, abfd,
bfd_asymbol_name (p))) bfd_asymbol_name (p)))
goto error_return; return false;
if (! generic_link_add_symbol_list (abfd, info, symbol_count, symcount = _bfd_generic_link_get_symcount (abfd);
symbols = _bfd_generic_link_get_symbols (abfd);
if (! generic_link_add_symbol_list (abfd, info, symcount,
symbols, collect)) symbols, collect))
goto error_return; return false;
*pneeded = true; *pneeded = true;
goto successful_return; return true;
} }
/* P is a common symbol. */ /* P is a common symbol. */
@ -1077,9 +1096,9 @@ generic_link_check_archive_element (abfd, info, pneeded, collect)
file. This is for the -u option in the linker. */ file. This is for the -u option in the linker. */
if (! (*info->callbacks->add_archive_element) if (! (*info->callbacks->add_archive_element)
(info, abfd, bfd_asymbol_name (p))) (info, abfd, bfd_asymbol_name (p)))
goto error_return; return false;
*pneeded = true; *pneeded = true;
goto successful_return; return true;
} }
/* Turn the symbol into a common symbol but do not link in /* Turn the symbol into a common symbol but do not link in
@ -1110,16 +1129,7 @@ generic_link_check_archive_element (abfd, info, pneeded, collect)
} }
/* This archive element is not needed. */ /* This archive element is not needed. */
successful_return:
if (symbols != NULL)
free (symbols);
return true; return true;
error_return:
if (symbols != NULL)
free (symbols);
return false;
} }
/* Add the symbols from an object file to the global hash table. ABFD /* Add the symbols from an object file to the global hash table. ABFD
@ -1174,6 +1184,7 @@ generic_link_add_symbol_list (abfd, info, symbol_count, symbols, collect)
else else
string = NULL; string = NULL;
h = NULL;
if (! (_bfd_generic_link_add_one_symbol if (! (_bfd_generic_link_add_one_symbol
(info, abfd, name, p->flags, bfd_get_section (p), (info, abfd, name, p->flags, bfd_get_section (p),
p->value, string, false, collect, p->value, string, false, collect,
@ -1202,6 +1213,11 @@ generic_link_add_symbol_list (abfd, info, symbol_count, symbols, collect)
if (bfd_is_com_section (bfd_get_section (p))) if (bfd_is_com_section (bfd_get_section (p)))
p->flags |= BSF_OLD_COMMON; p->flags |= BSF_OLD_COMMON;
} }
/* Store a back pointer from the symbol to the hash
table entry for the benefit of relaxation code until
it gets rewritten to not use asymbol structures. */
p->udata = (PTR) h;
} }
} }
} }
@ -1282,7 +1298,8 @@ static const enum link_action link_action[8][7] =
COLLECT is true if we should automatically collect gcc constructor COLLECT is true if we should automatically collect gcc constructor
or destructor names as collect2 does. or destructor names as collect2 does.
HASHP, if not NULL, is a place to store the created hash table HASHP, if not NULL, is a place to store the created hash table
entry. */ entry; if *HASHP is not NULL, the caller has already looked up
the hash table entry, and stored it in *HASHP.
boolean boolean
_bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
@ -1323,12 +1340,20 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
else else
row = DEF_ROW; row = DEF_ROW;
h = bfd_link_hash_lookup (info->hash, name, true, copy, false); if (hashp != NULL && *hashp != NULL)
if (h == (struct bfd_link_hash_entry *) NULL)
{ {
if (hashp != (struct bfd_link_hash_entry **) NULL) h = *hashp;
*hashp = NULL; BFD_ASSERT (strcmp (h->name, name) == 0);
return false; }
else
{
h = bfd_link_hash_lookup (info->hash, name, true, copy, false);
if (h == NULL)
{
if (hashp != NULL)
*hashp = NULL;
return false;
}
} }
if (info->notice_hash != (struct bfd_hash_table *) NULL if (info->notice_hash != (struct bfd_hash_table *) NULL
@ -1576,8 +1601,7 @@ _bfd_generic_final_link (abfd, info)
abfd->symcount = 0; abfd->symcount = 0;
outsymalloc = 0; outsymalloc = 0;
/* Build the output symbol table. This also reads in the symbols /* Build the output symbol table. */
for all the input BFDs, keeping them in the outsymbols field. */
for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next) for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next)
if (! _bfd_generic_link_output_symbols (abfd, sub, info, &outsymalloc)) if (! _bfd_generic_link_output_symbols (abfd, sub, info, &outsymalloc))
return false; return false;
@ -1609,24 +1633,30 @@ _bfd_generic_final_link (abfd, info)
{ {
asection *input_section; asection *input_section;
bfd *input_bfd; bfd *input_bfd;
bfd_size_type relsize; long relsize;
arelent **relocs; arelent **relocs;
bfd_size_type reloc_count; asymbol **symbols;
long reloc_count;
input_section = p->u.indirect.section; input_section = p->u.indirect.section;
input_bfd = input_section->owner; input_bfd = input_section->owner;
relsize = bfd_get_reloc_upper_bound (input_bfd, relsize = bfd_get_reloc_upper_bound (input_bfd,
input_section); input_section);
if (relsize < 0)
return false;
relocs = (arelent **) malloc ((size_t) relsize); relocs = (arelent **) malloc ((size_t) relsize);
if (!relocs && relsize != 0) if (!relocs && relsize != 0)
{ {
bfd_set_error (bfd_error_no_memory); bfd_set_error (bfd_error_no_memory);
return false; return false;
} }
reloc_count = symbols = _bfd_generic_link_get_symbols (input_bfd);
bfd_canonicalize_reloc (input_bfd, input_section, reloc_count = bfd_canonicalize_reloc (input_bfd,
relocs, input_section,
bfd_get_outsymbols (input_bfd)); relocs,
symbols);
if (reloc_count < 0)
return false;
BFD_ASSERT (reloc_count == input_section->reloc_count); BFD_ASSERT (reloc_count == input_section->reloc_count);
o->reloc_count += reloc_count; o->reloc_count += reloc_count;
free (relocs); free (relocs);
@ -1722,23 +1752,11 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
struct bfd_link_info *info; struct bfd_link_info *info;
size_t *psymalloc; size_t *psymalloc;
{ {
size_t symsize;
asymbol **sym_ptr; asymbol **sym_ptr;
asymbol **sym_end; asymbol **sym_end;
/* Do not clobber outsymbols if they have already been created. */ if (! generic_link_read_symbols (input_bfd))
if (input_bfd->outsymbols == NULL) return false;
{
symsize = get_symtab_upper_bound (input_bfd);
input_bfd->outsymbols = (asymbol **) bfd_alloc (input_bfd, symsize);
if (!input_bfd->outsymbols)
{
bfd_set_error (bfd_error_no_memory);
return false;
}
input_bfd->symcount = bfd_canonicalize_symtab (input_bfd,
input_bfd->outsymbols);
}
/* Create a filename symbol if we are supposed to. */ /* Create a filename symbol if we are supposed to. */
if (info->create_object_symbols_section != (asection *) NULL) if (info->create_object_symbols_section != (asection *) NULL)
@ -1772,8 +1790,8 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
/* Adjust the values of the globally visible symbols, and write out /* Adjust the values of the globally visible symbols, and write out
local symbols. */ local symbols. */
sym_ptr = bfd_get_outsymbols (input_bfd); sym_ptr = _bfd_generic_link_get_symbols (input_bfd);
sym_end = sym_ptr + bfd_get_symcount (input_bfd); sym_end = sym_ptr + _bfd_generic_link_get_symcount (input_bfd);
for (; sym_ptr < sym_end; sym_ptr++) for (; sym_ptr < sym_end; sym_ptr++)
{ {
asymbol *sym; asymbol *sym;
@ -2252,20 +2270,8 @@ default_indirect_link_order (output_bfd, info, output_section, link_order)
retrieved them by this point, but we may be being called by a retrieved them by this point, but we may be being called by a
specific linker when linking different types of object files specific linker when linking different types of object files
together. */ together. */
if (bfd_get_outsymbols (input_bfd) == (asymbol **) NULL) if (! generic_link_read_symbols (input_bfd))
{ return false;
size_t symsize;
symsize = get_symtab_upper_bound (input_bfd);
input_bfd->outsymbols = (asymbol **) bfd_alloc (input_bfd, symsize);
if (!input_bfd->outsymbols)
{
bfd_set_error (bfd_error_no_memory);
return false;
}
input_bfd->symcount = bfd_canonicalize_symtab (input_bfd,
input_bfd->outsymbols);
}
/* Get and relocate the section contents. */ /* Get and relocate the section contents. */
contents = (bfd_byte *) malloc (bfd_section_size (input_bfd, input_section)); contents = (bfd_byte *) malloc (bfd_section_size (input_bfd, input_section));
@ -2276,7 +2282,7 @@ default_indirect_link_order (output_bfd, info, output_section, link_order)
} }
new_contents = (bfd_get_relocated_section_contents new_contents = (bfd_get_relocated_section_contents
(output_bfd, info, link_order, contents, info->relocateable, (output_bfd, info, link_order, contents, info->relocateable,
bfd_get_outsymbols (input_bfd))); _bfd_generic_link_get_symbols (input_bfd)));
if (!new_contents) if (!new_contents)
goto error_return; goto error_return;