* 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)
* 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
linking.
(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_aouthdr *internal_a = (struct internal_aouthdr *) aouthdr;
ecoff_data_type *ecoff;
asection *regsec;
if (ecoff_mkobject (abfd) == false)
return NULL;
@ -108,13 +107,6 @@ ecoff_mkobject_hook (abfd, filehdr, aouthdr)
ecoff->gp_size = 8;
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)
{
int i;
@ -184,15 +176,6 @@ ecoff_new_section_hook (abfd, section)
/* An Irix 4 shared libary. */
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
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 *oinfo = &ecoff_data (obfd)->debug_info;
register int i;
asymbol **sym_ptr_ptr;
size_t c;
boolean local;
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;
/* 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;
}
/* Get the size of the section headers. We do not output the .reginfo
section. */
/* Get the size of the section headers. */
/*ARGSUSED*/
int
@ -2304,8 +2295,7 @@ ecoff_sizeof_headers (abfd, reloc)
for (current = abfd->sections;
current != (asection *)NULL;
current = current->next)
if (strcmp (current->name, REGINFO) != 0)
++c;
++c;
ret = (bfd_coff_filhsz (abfd)
+ bfd_coff_aoutsz (abfd)
@ -2313,9 +2303,7 @@ ecoff_sizeof_headers (abfd, reloc)
return BFD_ALIGN (ret, 16);
}
/* Get the contents of a section. This is where we handle reading the
.reginfo section, which implicitly holds the contents of an
ecoff_reginfo structure. */
/* Get the contents of a section. */
boolean
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;
bfd_size_type count;
{
ecoff_data_type *tdata = ecoff_data (abfd);
struct ecoff_reginfo s;
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;
return _bfd_generic_get_section_contents (abfd, section, location,
offset, count);
}
/* Calculate the file position for each section, and set
@ -2369,8 +2339,7 @@ ecoff_compute_section_file_positions (abfd)
unsigned int alignment_power;
/* Only deal with sections which have contents */
if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0
|| strcmp (current->name, REGINFO) == 0)
if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0)
continue;
/* For the Alpha ECOFF .pdata section the lnnoptr field is
@ -2460,8 +2429,6 @@ ecoff_compute_reloc_file_positions (abfd)
current != (asection *)NULL;
current = current->next)
{
if (strcmp (current->name, REGINFO) == 0)
continue;
if (current->reloc_count == 0)
current->rel_filepos = 0;
else
@ -2490,9 +2457,7 @@ ecoff_compute_reloc_file_positions (abfd)
return reloc_size;
}
/* Set the contents of a section. This is where we handle setting the
contents of the .reginfo section, which implicitly holds a
ecoff_reginfo structure. */
/* Set the contents of a section. */
boolean
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)
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
|| bfd_write (location, 1, count, abfd) != count)
return false;
@ -2556,6 +2488,76 @@ ecoff_set_section_contents (abfd, section, location, offset, count)
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
is passed to bfd_ecoff_debug_externals. */
@ -2681,8 +2683,6 @@ ecoff_write_object_contents (abfd)
current != (asection *)NULL;
current = current->next)
{
if (strcmp (current->name, REGINFO) == 0)
continue;
current->target_index = count;
++count;
}
@ -2727,12 +2727,6 @@ ecoff_write_object_contents (abfd)
struct internal_scnhdr section;
bfd_vma vma;
if (strcmp (current->name, REGINFO) == 0)
{
BFD_ASSERT (current->reloc_count == 0);
continue;
}
++internal_f.f_nscns;
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;
h = NULL;
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, name, BSF_GLOBAL, section, value,
(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)
{
/* 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;
p != (struct bfd_link_order *) NULL;
p = p->next)

View File

@ -412,6 +412,8 @@ SUBSUBSECTION
static struct bfd_hash_entry *generic_link_hash_newfunc
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
const char *));
static boolean generic_link_read_symbols
PARAMS ((bfd *));
static boolean generic_link_add_symbols
PARAMS ((bfd *, struct bfd_link_info *, boolean collect));
static boolean generic_link_add_object_symbols
@ -610,6 +612,40 @@ _bfd_generic_link_hash_table_create (abfd)
}
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
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;
boolean collect;
{
size_t symsize;
asymbol **symbols;
bfd_size_type symbol_count;
boolean result;
symsize = get_symtab_upper_bound (abfd);
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;
if (! generic_link_read_symbols (abfd))
return false;
return generic_link_add_symbol_list (abfd, info,
_bfd_generic_link_get_symcount (abfd),
_bfd_generic_link_get_symbols (abfd),
collect);
}
/* 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 collect;
{
size_t symsize;
asymbol **symbols = NULL;
bfd_size_type symbol_count;
asymbol **pp, **ppend;
*pneeded = false;
symsize = get_symtab_upper_bound (abfd);
symbols = (asymbol **) malloc (symsize);
if (symbols == NULL && symsize != 0)
{
bfd_set_error (bfd_error_no_memory);
goto error_return;
}
if (! generic_link_read_symbols (abfd))
return false;
symbol_count = bfd_canonicalize_symtab (abfd, symbols);
pp = symbols;
ppend = symbols + symbol_count;
pp = _bfd_generic_link_get_symbols (abfd);
ppend = pp + _bfd_generic_link_get_symcount (abfd);
for (; pp < ppend; pp++)
{
asymbol *p;
@ -1052,15 +1066,20 @@ generic_link_check_archive_element (abfd, info, pneeded, collect)
if (! bfd_is_com_section (p->section))
{
bfd_size_type symcount;
asymbol **symbols;
/* This object file defines this symbol, so pull it in. */
if (! (*info->callbacks->add_archive_element) (info, abfd,
bfd_asymbol_name (p)))
goto error_return;
if (! generic_link_add_symbol_list (abfd, info, symbol_count,
return false;
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))
goto error_return;
return false;
*pneeded = true;
goto successful_return;
return true;
}
/* 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. */
if (! (*info->callbacks->add_archive_element)
(info, abfd, bfd_asymbol_name (p)))
goto error_return;
return false;
*pneeded = true;
goto successful_return;
return true;
}
/* 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. */
successful_return:
if (symbols != NULL)
free (symbols);
return true;
error_return:
if (symbols != NULL)
free (symbols);
return false;
}
/* 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
string = NULL;
h = NULL;
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, name, p->flags, bfd_get_section (p),
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)))
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
or destructor names as collect2 does.
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
_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
row = DEF_ROW;
h = bfd_link_hash_lookup (info->hash, name, true, copy, false);
if (h == (struct bfd_link_hash_entry *) NULL)
if (hashp != NULL && *hashp != NULL)
{
if (hashp != (struct bfd_link_hash_entry **) NULL)
*hashp = NULL;
return false;
h = *hashp;
BFD_ASSERT (strcmp (h->name, name) == 0);
}
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
@ -1576,8 +1601,7 @@ _bfd_generic_final_link (abfd, info)
abfd->symcount = 0;
outsymalloc = 0;
/* Build the output symbol table. This also reads in the symbols
for all the input BFDs, keeping them in the outsymbols field. */
/* Build the output symbol table. */
for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next)
if (! _bfd_generic_link_output_symbols (abfd, sub, info, &outsymalloc))
return false;
@ -1609,24 +1633,30 @@ _bfd_generic_final_link (abfd, info)
{
asection *input_section;
bfd *input_bfd;
bfd_size_type relsize;
long relsize;
arelent **relocs;
bfd_size_type reloc_count;
asymbol **symbols;
long reloc_count;
input_section = p->u.indirect.section;
input_bfd = input_section->owner;
relsize = bfd_get_reloc_upper_bound (input_bfd,
input_section);
if (relsize < 0)
return false;
relocs = (arelent **) malloc ((size_t) relsize);
if (!relocs && relsize != 0)
{
bfd_set_error (bfd_error_no_memory);
return false;
}
reloc_count =
bfd_canonicalize_reloc (input_bfd, input_section,
relocs,
bfd_get_outsymbols (input_bfd));
symbols = _bfd_generic_link_get_symbols (input_bfd);
reloc_count = bfd_canonicalize_reloc (input_bfd,
input_section,
relocs,
symbols);
if (reloc_count < 0)
return false;
BFD_ASSERT (reloc_count == input_section->reloc_count);
o->reloc_count += reloc_count;
free (relocs);
@ -1722,23 +1752,11 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
struct bfd_link_info *info;
size_t *psymalloc;
{
size_t symsize;
asymbol **sym_ptr;
asymbol **sym_end;
/* Do not clobber outsymbols if they have already been created. */
if (input_bfd->outsymbols == NULL)
{
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);
}
if (! generic_link_read_symbols (input_bfd))
return false;
/* Create a filename symbol if we are supposed to. */
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
local symbols. */
sym_ptr = bfd_get_outsymbols (input_bfd);
sym_end = sym_ptr + bfd_get_symcount (input_bfd);
sym_ptr = _bfd_generic_link_get_symbols (input_bfd);
sym_end = sym_ptr + _bfd_generic_link_get_symcount (input_bfd);
for (; sym_ptr < sym_end; sym_ptr++)
{
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
specific linker when linking different types of object files
together. */
if (bfd_get_outsymbols (input_bfd) == (asymbol **) NULL)
{
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);
}
if (! generic_link_read_symbols (input_bfd))
return false;
/* Get and relocate the section contents. */
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
(output_bfd, info, link_order, contents, info->relocateable,
bfd_get_outsymbols (input_bfd)));
_bfd_generic_link_get_symbols (input_bfd)));
if (!new_contents)
goto error_return;