mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-22 02:50:08 +08:00
* 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:
@ -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.
|
||||||
|
174
bfd/ecoff.c
174
bfd/ecoff.c
@ -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,7 +2295,6 @@ 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)
|
||||||
@ -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);
|
|
||||||
struct ecoff_reginfo s;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (strcmp (section->name, REGINFO) != 0)
|
|
||||||
return _bfd_generic_get_section_contents (abfd, section, location,
|
return _bfd_generic_get_section_contents (abfd, section, location,
|
||||||
offset, count);
|
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,42 +2481,79 @@ 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)
|
if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
|
||||||
{
|
|| bfd_write (location, 1, count, abfd) != count)
|
||||||
ecoff_data_type *tdata = ecoff_data (abfd);
|
return false;
|
||||||
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
|
/* Get the GP value for an ECOFF file. This is a hook used by
|
||||||
|| bfd_write (location, 1, count, abfd) != count)
|
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;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -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)
|
||||||
|
176
bfd/linker.c
176
bfd/linker.c
@ -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;
|
|
||||||
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;
|
return false;
|
||||||
}
|
return generic_link_add_symbol_list (abfd, info,
|
||||||
symbol_count = bfd_canonicalize_symtab (abfd, symbols);
|
_bfd_generic_link_get_symcount (abfd),
|
||||||
|
_bfd_generic_link_get_symbols (abfd),
|
||||||
result = generic_link_add_symbol_list (abfd, info, symbol_count, symbols,
|
|
||||||
collect);
|
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,13 +1340,21 @@ _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;
|
||||||
|
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;
|
*hashp = NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (info->notice_hash != (struct bfd_hash_table *) NULL
|
if (info->notice_hash != (struct bfd_hash_table *) NULL
|
||||||
&& (bfd_hash_lookup (info->notice_hash, name, false, false)
|
&& (bfd_hash_lookup (info->notice_hash, name, false, false)
|
||||||
@ -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,
|
||||||
|
input_section,
|
||||||
relocs,
|
relocs,
|
||||||
bfd_get_outsymbols (input_bfd));
|
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)
|
|
||||||
{
|
|
||||||
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;
|
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))
|
||||||
{
|
|
||||||
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;
|
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;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user