Distinguish a weak defined symbol from a regular defined symbol.

* linker.c (enum link_action): Add DEFW.
	(link_action): Add bfd_link_hash_defweak column.
	(_bfd_generic_link_add_one_symbol): Add DEFW case.  Handle
	bfd_link_hash_defweak in a few other cases.
	* Many files (bfd_link_hash_undefweak): Renamed from
	bfd_link_hash_weak.
	* aoutx.h (aout_link_write_symbols): Handle bfd_link_hash_defweak.
	(aout_link_write_other_symbol): Likewise.
	(aout_link_input_section_std): Likewise.
	(aout_link_input_section_ext): Likewise.
	* bout.c (get_value): Likewise.
	* coff-a29k.c (coff_a29k_relocate_section): Likewise.
	* coff-alpha.c (alpha_convert_external_reloc): Likewise.
	(alpha_relocate_section): Likewise.
	* coff-mips.c (mips_relocate_section): Likewise.
	(mips_relax_section): Likewise.
	(bfd_mips_ecoff_create_embedded_relocs): Likewise.
	* cofflink.c (coff_write_global_sym): Likewise.
	(_bfd_coff_generic_relocate_section): Likewise.
	* ecoff.c (ecoff_link_add_externals): Likewise.
	(ecoff_link_write_external): LIkewise.
	* elf32-hppa.c (elf32_hppa_relocate_section): Likewise.
	(elf32_hppa_size_stubs): Likewise.
	* elf32-i386.c (elf_i386_adjust_dynamic_symbol): Likewise.
	(elf_i386_relocate_section): Likewise.
	(elf_i386_finish_dynamic_symbol): Likewise.
	* elf32-mips.c (mips_elf_output_extsym): Likewise.
	(mips_elf_relocate_section): Likewise.
	* elf32-sparc.c (elf32_sparc_adjust_dynamic_symbol): Likewise.
	(elf32_sparc_relocate_section): Likewise.
	* elfcode.h (elf_link_add_object_symbols): Likewise.
	(elf_adjust_dynamic_symbol): Likewise.
	(elf_bfd_final_link): Likewise.
	(elf_link_output_extsym): Likewise.
	* i386linux.c (linux_add_one_symbol): Likewise.
	(linux_tally_symbols): Likewise.
	(linux_finish_dynamic_link): Likewise.
	* linker.c (_bfd_generic_link_output_symbols): Likewise.
	(set_symbol_from_hash): Likewise.
	* reloc16.c (bfd_coff_reloc16_get_value): Likewise.
	(bfd_perform_slip): Likewise.
	* sunos.c (sunos_add_one_symbol): Likewise.
	(sunos_scan_std_relocs): Likewise.
	(sunos_scan_ext_relocs): Likewise.
	(sunos_scan_dynamic_symbol): Likewise.
	(sunos_write_dynamic_symbol): Likewise.
This commit is contained in:
Ian Lance Taylor
1995-02-06 20:01:08 +00:00
parent ebc4ca90f9
commit 6c97aedf26
9 changed files with 423 additions and 177 deletions

View File

@ -1,3 +1,53 @@
Mon Feb 6 14:25:24 1995 Ian Lance Taylor <ian@cygnus.com>
Distinguish a weak defined symbol from a regular defined symbol.
* linker.c (enum link_action): Add DEFW.
(link_action): Add bfd_link_hash_defweak column.
(_bfd_generic_link_add_one_symbol): Add DEFW case. Handle
bfd_link_hash_defweak in a few other cases.
* Many files (bfd_link_hash_undefweak): Renamed from
bfd_link_hash_weak.
* aoutx.h (aout_link_write_symbols): Handle bfd_link_hash_defweak.
(aout_link_write_other_symbol): Likewise.
(aout_link_input_section_std): Likewise.
(aout_link_input_section_ext): Likewise.
* bout.c (get_value): Likewise.
* coff-a29k.c (coff_a29k_relocate_section): Likewise.
* coff-alpha.c (alpha_convert_external_reloc): Likewise.
(alpha_relocate_section): Likewise.
* coff-mips.c (mips_relocate_section): Likewise.
(mips_relax_section): Likewise.
(bfd_mips_ecoff_create_embedded_relocs): Likewise.
* cofflink.c (coff_write_global_sym): Likewise.
(_bfd_coff_generic_relocate_section): Likewise.
* ecoff.c (ecoff_link_add_externals): Likewise.
(ecoff_link_write_external): LIkewise.
* elf32-hppa.c (elf32_hppa_relocate_section): Likewise.
(elf32_hppa_size_stubs): Likewise.
* elf32-i386.c (elf_i386_adjust_dynamic_symbol): Likewise.
(elf_i386_relocate_section): Likewise.
(elf_i386_finish_dynamic_symbol): Likewise.
* elf32-mips.c (mips_elf_output_extsym): Likewise.
(mips_elf_relocate_section): Likewise.
* elf32-sparc.c (elf32_sparc_adjust_dynamic_symbol): Likewise.
(elf32_sparc_relocate_section): Likewise.
* elfcode.h (elf_link_add_object_symbols): Likewise.
(elf_adjust_dynamic_symbol): Likewise.
(elf_bfd_final_link): Likewise.
(elf_link_output_extsym): Likewise.
* i386linux.c (linux_add_one_symbol): Likewise.
(linux_tally_symbols): Likewise.
(linux_finish_dynamic_link): Likewise.
* linker.c (_bfd_generic_link_output_symbols): Likewise.
(set_symbol_from_hash): Likewise.
* reloc16.c (bfd_coff_reloc16_get_value): Likewise.
(bfd_perform_slip): Likewise.
* sunos.c (sunos_add_one_symbol): Likewise.
(sunos_scan_std_relocs): Likewise.
(sunos_scan_ext_relocs): Likewise.
(sunos_scan_dynamic_symbol): Likewise.
(sunos_write_dynamic_symbol): Likewise.
Mon Feb 6 03:20:17 1995 Ken Raeburn <raeburn@cujo.cygnus.com> Mon Feb 6 03:20:17 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
Changes from Bryan Ford, baford@schirf.cs.utah.edu: Changes from Bryan Ford, baford@schirf.cs.utah.edu:

View File

@ -562,35 +562,33 @@ NAME(aout,some_aout_object_p) (abfd, execp, callback_to_real_object_p)
result = (*callback_to_real_object_p)(abfd); result = (*callback_to_real_object_p)(abfd);
#ifdef STAT_FOR_EXEC
/* The original heuristic doesn't work in some important cases. The
* a.out file has no information about the text start address. For
* files (like kernels) linked to non-standard addresses (ld -Ttext
* nnn) the entry point may not be between the default text start
* (obj_textsec(abfd)->vma) and (obj_textsec(abfd)->vma) + text size
* This is not just a mach issue. Many kernels are loaded at non
* standard addresses.
*/
{
struct stat stat_buf;
if (abfd->iostream
&& (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0)
&& ((stat_buf.st_mode & 0111) != 0))
abfd->flags |= EXEC_P;
}
#else /* ! defined (STAT_FOR_EXEC) */
/* Now that the segment addresses have been worked out, take a better /* Now that the segment addresses have been worked out, take a better
guess at whether the file is executable. If the entry point guess at whether the file is executable. If the entry point
is within the text segment, assume it is. (This makes files is within the text segment, assume it is. (This makes files
executable even if their entry point address is 0, as long as executable even if their entry point address is 0, as long as
their text starts at zero.) their text starts at zero.). */
At some point we should probably break down and stat the file and
declare it executable if (one of) its 'x' bits are on... */
if ((execp->a_entry >= obj_textsec(abfd)->vma) && if ((execp->a_entry >= obj_textsec(abfd)->vma) &&
(execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size)) (execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size))
abfd->flags |= EXEC_P; abfd->flags |= EXEC_P;
#endif /* ! defined (STAT_FOR_EXEC) */ #ifdef STAT_FOR_EXEC
else
{
struct stat stat_buf;
/* The original heuristic doesn't work in some important cases.
The a.out file has no information about the text start
address. For files (like kernels) linked to non-standard
addresses (ld -Ttext nnn) the entry point may not be between
the default text start (obj_textsec(abfd)->vma) and
(obj_textsec(abfd)->vma) + text size. This is not just a mach
issue. Many kernels are loaded at non standard addresses. */
if (abfd->iostream
&& (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0)
&& ((stat_buf.st_mode & 0111) != 0))
abfd->flags |= EXEC_P;
}
#endif /* STAT_FOR_EXEC */
if (result) if (result)
{ {
#if 0 /* These should be set correctly anyways. */ #if 0 /* These should be set correctly anyways. */
@ -3789,6 +3787,7 @@ aout_link_write_symbols (finfo, input_bfd)
else if (((type & N_TYPE) == N_INDR else if (((type & N_TYPE) == N_INDR
&& (hresolve == (struct aout_link_hash_entry *) NULL && (hresolve == (struct aout_link_hash_entry *) NULL
|| (hresolve->root.type != bfd_link_hash_defined || (hresolve->root.type != bfd_link_hash_defined
&& hresolve->root.type != bfd_link_hash_defweak
&& hresolve->root.type != bfd_link_hash_common))) && hresolve->root.type != bfd_link_hash_common)))
|| type == N_WARNING) || type == N_WARNING)
{ {
@ -3841,13 +3840,14 @@ aout_link_write_symbols (finfo, input_bfd)
break; break;
} }
} }
else if (hresolve->root.type == bfd_link_hash_defined) else if (hresolve->root.type == bfd_link_hash_defined
|| hresolve->root.type == bfd_link_hash_defweak)
{ {
asection *input_section; asection *input_section;
asection *output_section; asection *output_section;
/* This case means a common symbol which was turned /* This case usually means a common symbol which was
into a defined symbol. */ turned into a defined symbol. */
input_section = hresolve->root.u.def.section; input_section = hresolve->root.u.def.section;
output_section = input_section->output_section; output_section = input_section->output_section;
BFD_ASSERT (bfd_is_abs_section (output_section) BFD_ASSERT (bfd_is_abs_section (output_section)
@ -3868,17 +3868,25 @@ aout_link_write_symbols (finfo, input_bfd)
type &=~ N_TYPE; type &=~ N_TYPE;
if (output_section == obj_textsec (output_bfd)) if (output_section == obj_textsec (output_bfd))
type |= N_TEXT; type |= (hresolve->root.type == bfd_link_hash_defined
? N_TEXT
: N_WEAKT);
else if (output_section == obj_datasec (output_bfd)) else if (output_section == obj_datasec (output_bfd))
type |= N_DATA; type |= (hresolve->root.type == bfd_link_hash_defined
? N_DATA
: N_WEAKD);
else if (output_section == obj_bsssec (output_bfd)) else if (output_section == obj_bsssec (output_bfd))
type |= N_BSS; type |= (hresolve->root.type == bfd_link_hash_defined
? N_BSS
: N_WEAKB);
else else
type |= N_ABS; type |= (hresolve->root.type == bfd_link_hash_defined
? N_ABS
: N_WEAKA);
} }
else if (hresolve->root.type == bfd_link_hash_common) else if (hresolve->root.type == bfd_link_hash_common)
val = hresolve->root.u.c.size; val = hresolve->root.u.c.size;
else if (hresolve->root.type == bfd_link_hash_weak) else if (hresolve->root.type == bfd_link_hash_undefweak)
{ {
val = 0; val = 0;
type = N_WEAKU; type = N_WEAKU;
@ -4030,6 +4038,7 @@ aout_link_write_other_symbol (h, data)
val = 0; val = 0;
break; break;
case bfd_link_hash_defined: case bfd_link_hash_defined:
case bfd_link_hash_defweak:
{ {
asection *sec; asection *sec;
@ -4037,13 +4046,14 @@ aout_link_write_other_symbol (h, data)
BFD_ASSERT (bfd_is_abs_section (sec) BFD_ASSERT (bfd_is_abs_section (sec)
|| sec->owner == output_bfd); || sec->owner == output_bfd);
if (sec == obj_textsec (output_bfd)) if (sec == obj_textsec (output_bfd))
type = N_TEXT | N_EXT; type = h->root.type == bfd_link_hash_defined ? N_TEXT : N_WEAKT;
else if (sec == obj_datasec (output_bfd)) else if (sec == obj_datasec (output_bfd))
type = N_DATA | N_EXT; type = h->root.type == bfd_link_hash_defined ? N_DATA : N_WEAKD;
else if (sec == obj_bsssec (output_bfd)) else if (sec == obj_bsssec (output_bfd))
type = N_BSS | N_EXT; type = h->root.type == bfd_link_hash_defined ? N_BSS : N_WEAKB;
else else
type = N_ABS | N_EXT; type = h->root.type == bfd_link_hash_defined ? N_ABS : N_WEAKA;
type |= N_EXT;
val = (h->root.u.def.value val = (h->root.u.def.value
+ sec->vma + sec->vma
+ h->root.u.def.section->output_offset); + h->root.u.def.section->output_offset);
@ -4053,7 +4063,7 @@ aout_link_write_other_symbol (h, data)
type = N_UNDF | N_EXT; type = N_UNDF | N_EXT;
val = h->root.u.c.size; val = h->root.u.c.size;
break; break;
case bfd_link_hash_weak: case bfd_link_hash_undefweak:
type = N_WEAKU; type = N_WEAKU;
val = 0; val = 0;
case bfd_link_hash_indirect: case bfd_link_hash_indirect:
@ -4305,7 +4315,8 @@ aout_link_input_section_std (finfo, input_bfd, input_section, relocs,
is what the native linker does. */ is what the native linker does. */
h = sym_hashes[r_index]; h = sym_hashes[r_index];
if (h != (struct aout_link_hash_entry *) NULL if (h != (struct aout_link_hash_entry *) NULL
&& h->root.type == bfd_link_hash_defined) && (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak))
{ {
asection *output_section; asection *output_section;
@ -4443,14 +4454,15 @@ aout_link_input_section_std (finfo, input_bfd, input_section, relocs,
} }
if (h != (struct aout_link_hash_entry *) NULL if (h != (struct aout_link_hash_entry *) NULL
&& h->root.type == bfd_link_hash_defined) && (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak))
{ {
relocation = (h->root.u.def.value relocation = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma + h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset); + h->root.u.def.section->output_offset);
} }
else if (h != (struct aout_link_hash_entry *) NULL else if (h != (struct aout_link_hash_entry *) NULL
&& h->root.type == bfd_link_hash_weak) && h->root.type == bfd_link_hash_undefweak)
relocation = 0; relocation = 0;
else else
{ {
@ -4606,7 +4618,8 @@ aout_link_input_section_ext (finfo, input_bfd, input_section, relocs,
is what the native linker does. */ is what the native linker does. */
h = sym_hashes[r_index]; h = sym_hashes[r_index];
if (h != (struct aout_link_hash_entry *) NULL if (h != (struct aout_link_hash_entry *) NULL
&& h->root.type == bfd_link_hash_defined) && (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak))
{ {
asection *output_section; asection *output_section;
@ -4761,14 +4774,15 @@ aout_link_input_section_ext (finfo, input_bfd, input_section, relocs,
} }
if (h != (struct aout_link_hash_entry *) NULL if (h != (struct aout_link_hash_entry *) NULL
&& h->root.type == bfd_link_hash_defined) && (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak))
{ {
relocation = (h->root.u.def.value relocation = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma + h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset); + h->root.u.def.section->output_offset);
} }
else if (h != (struct aout_link_hash_entry *) NULL else if (h != (struct aout_link_hash_entry *) NULL
&& h->root.type == bfd_link_hash_weak) && h->root.type == bfd_link_hash_undefweak)
relocation = 0; relocation = 0;
else else
{ {

View File

@ -385,7 +385,8 @@ coff_a29k_relocate_section (output_bfd, info, input_bfd, input_section,
} }
else else
{ {
if (h->root.type == bfd_link_hash_defined) if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{ {
sec = h->root.u.def.section; sec = h->root.u.def.section;
val = (h->root.u.def.value val = (h->root.u.def.value

View File

@ -1,5 +1,5 @@
/* Generic ECOFF (Extended-COFF) routines. /* Generic ECOFF (Extended-COFF) routines.
Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
Original version by Per Bothner. Original version by Per Bothner.
Full support added by Ian Lance Taylor, ian@cygnus.com. Full support added by Ian Lance Taylor, ian@cygnus.com.
@ -1358,7 +1358,7 @@ ecoff_type_to_string (abfd, fdr, indx)
} qualifiers[7]; } qualifiers[7];
unsigned int basic_type; unsigned int basic_type;
int i; int i;
static char buffer1[1024]; char buffer1[1024];
static char buffer2[1024]; static char buffer2[1024];
char *p1 = buffer1; char *p1 = buffer1;
char *p2 = buffer2; char *p2 = buffer2;
@ -2027,6 +2027,8 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
FDR *fdr_hold; FDR *fdr_hold;
boolean stabs; boolean stabs;
offset += section->vma;
/* If we're not in the .text section, we don't have any line /* If we're not in the .text section, we don't have any line
numbers. */ numbers. */
if (strcmp (section->name, _TEXT) != 0 if (strcmp (section->name, _TEXT) != 0
@ -2091,14 +2093,14 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
list of procedure descriptors (PDR). PDR's also have an list of procedure descriptors (PDR). PDR's also have an
address, which is relative to the FDR address, and are also address, which is relative to the FDR address, and are also
stored in increasing memory order. */ stored in increasing memory order. */
if (offset < fdr_ptr->adr)
return false;
offset -= fdr_ptr->adr; offset -= fdr_ptr->adr;
external_pdr_size = debug_swap->external_pdr_size; external_pdr_size = debug_swap->external_pdr_size;
pdr_ptr = ((char *) debug_info->external_pdr pdr_ptr = ((char *) debug_info->external_pdr
+ fdr_ptr->ipdFirst * external_pdr_size); + fdr_ptr->ipdFirst * external_pdr_size);
pdr_end = pdr_ptr + fdr_ptr->cpd * external_pdr_size; pdr_end = pdr_ptr + fdr_ptr->cpd * external_pdr_size;
(*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
if (offset < pdr.adr)
return false;
/* The address of the first PDR is an offset which applies to /* The address of the first PDR is an offset which applies to
the addresses of all the PDR's. */ the addresses of all the PDR's. */
@ -2109,7 +2111,7 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
pdr_ptr += external_pdr_size) pdr_ptr += external_pdr_size)
{ {
(*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr); (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
if (offset < pdr.adr) if (offset < pdr.adr - first_off)
break; break;
} }
@ -3860,6 +3862,9 @@ ecoff_link_add_archive_symbols (abfd, info)
if (! bfd_has_map (abfd)) if (! bfd_has_map (abfd))
{ {
/* An empty archive is a special case. */
if (bfd_openr_next_archived_file (abfd, (bfd *) NULL) == NULL)
return true;
bfd_set_error (bfd_error_no_symbols); bfd_set_error (bfd_error_no_symbols);
return false; return false;
} }
@ -4360,7 +4365,8 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
if (h->abfd == (bfd *) NULL if (h->abfd == (bfd *) NULL
|| (! bfd_is_und_section (section) || (! bfd_is_und_section (section)
&& (! bfd_is_com_section (section) && (! bfd_is_com_section (section)
|| h->root.type != bfd_link_hash_defined))) || (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak))))
{ {
h->abfd = abfd; h->abfd = abfd;
h->esym = esym; h->esym = esym;
@ -4732,7 +4738,8 @@ ecoff_link_write_external (h, data)
h->esym.asym.value = 0; h->esym.asym.value = 0;
h->esym.asym.st = stGlobal; h->esym.asym.st = stGlobal;
if (h->root.type != bfd_link_hash_defined) if (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
h->esym.asym.sc = scAbs; h->esym.asym.sc = scAbs;
else else
{ {
@ -4787,12 +4794,13 @@ ecoff_link_write_external (h, data)
case bfd_link_hash_new: case bfd_link_hash_new:
abort (); abort ();
case bfd_link_hash_undefined: case bfd_link_hash_undefined:
case bfd_link_hash_weak: case bfd_link_hash_undefweak:
if (h->esym.asym.sc != scUndefined if (h->esym.asym.sc != scUndefined
&& h->esym.asym.sc != scSUndefined) && h->esym.asym.sc != scSUndefined)
h->esym.asym.sc = scUndefined; h->esym.asym.sc = scUndefined;
break; break;
case bfd_link_hash_defined: case bfd_link_hash_defined:
case bfd_link_hash_defweak:
if (h->esym.asym.sc == scUndefined if (h->esym.asym.sc == scUndefined
|| h->esym.asym.sc == scSUndefined) || h->esym.asym.sc == scSUndefined)
h->esym.asym.sc = scAbs; h->esym.asym.sc = scAbs;
@ -4979,7 +4987,7 @@ ecoff_reloc_link_order (output_bfd, info, output_section, link_order)
rel.address = link_order->offset; rel.address = link_order->offset;
rel.howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc); rel.howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc);
if (rel.howto == (const reloc_howto_type *) NULL) if (rel.howto == 0)
{ {
bfd_set_error (bfd_error_bad_value); bfd_set_error (bfd_error_bad_value);
return false; return false;

View File

@ -163,7 +163,10 @@ static file_ptr assign_file_position_for_section
static boolean assign_file_positions_except_relocs PARAMS ((bfd *, boolean)); static boolean assign_file_positions_except_relocs PARAMS ((bfd *, boolean));
static int elf_sort_hdrs PARAMS ((const PTR, const PTR)); static int elf_sort_hdrs PARAMS ((const PTR, const PTR));
static void assign_file_positions_for_relocs PARAMS ((bfd *)); static void assign_file_positions_for_relocs PARAMS ((bfd *));
static bfd_size_type get_program_header_size PARAMS ((bfd *)); static bfd_size_type get_program_header_size PARAMS ((bfd *,
Elf_Internal_Shdr **,
unsigned int,
bfd_vma));
static file_ptr map_program_segments static file_ptr map_program_segments
PARAMS ((bfd *, file_ptr, Elf_Internal_Shdr *, Elf_Internal_Shdr **, PARAMS ((bfd *, file_ptr, Elf_Internal_Shdr *, Elf_Internal_Shdr **,
bfd_size_type)); bfd_size_type));
@ -1719,20 +1722,121 @@ assign_file_position_for_section (i_shdrp, offset, align)
return offset; return offset;
} }
/* Get the size of the program header. This is called by the linker /* Get the size of the program header.
before any of the section VMA's are set, so it can't calculate the
correct value for a strange memory layout. */ SORTED_HDRS, if non-NULL, is an array of COUNT pointers to headers sorted
by VMA. Non-allocated sections (!SHF_ALLOC) must appear last. All
section VMAs and sizes are known so we can compute the correct value.
(??? This may not be perfectly true. What cases do we miss?)
If SORTED_HDRS is NULL we assume there are two segments: text and data
(exclusive of .interp and .dynamic).
If this is called by the linker before any of the section VMA's are set, it
can't calculate the correct value for a strange memory layout. This only
happens when SIZEOF_HEADERS is used in a linker script. In this case,
SORTED_HDRS is NULL and we assume the normal scenario of one text and one
data segment (exclusive of .interp and .dynamic).
??? User written scripts must either not use SIZEOF_HEADERS, or assume there
will be two segments. */
static bfd_size_type static bfd_size_type
get_program_header_size (abfd) get_program_header_size (abfd, sorted_hdrs, count, maxpagesize)
bfd *abfd; bfd *abfd;
Elf_Internal_Shdr **sorted_hdrs;
unsigned int count;
bfd_vma maxpagesize;
{ {
size_t segs; size_t segs;
asection *s; asection *s;
/* Assume we will need exactly two PT_LOAD segments: one for text /* We can't return a different result each time we're called. */
and one for data. */ if (elf_tdata (abfd)->program_header_size != 0)
segs = 2; return elf_tdata (abfd)->program_header_size;
if (sorted_hdrs != NULL)
{
unsigned int i;
unsigned int last_type;
Elf_Internal_Shdr **hdrpp;
/* What we think the current segment's offset is. */
bfd_vma p_offset;
/* What we think the current segment's address is. */
bfd_vma p_vaddr;
/* How big we think the current segment is. */
bfd_vma p_memsz;
/* What we think the current file offset is. */
bfd_vma file_offset;
bfd_vma next_offset;
/* Scan the headers and compute the number of segments required. This
code is intentionally similar to the code in map_program_segments.
The `sh_offset' field isn't valid at this point, so we keep our own
running total in `file_offset'.
This works because section VMAs are already known. */
segs = 1;
/* Make sure the first section goes in the first segment. */
file_offset = p_offset = sorted_hdrs[0]->sh_addr % maxpagesize;
p_vaddr = sorted_hdrs[0]->sh_addr;
p_memsz = 0;
last_type = SHT_PROGBITS;
for (i = 0, hdrpp = sorted_hdrs; i < count; i++, hdrpp++)
{
Elf_Internal_Shdr *hdr;
hdr = *hdrpp;
/* Ignore any section which will not be part of the process
image. */
if ((hdr->sh_flags & SHF_ALLOC) == 0)
continue;
/* Keep track of where this and the next sections go.
The section VMA must equal the file position modulo
the page size. */
file_offset += (hdr->sh_addr - file_offset) % maxpagesize;
next_offset = file_offset;
if (hdr->sh_type != SHT_NOBITS)
next_offset = file_offset + hdr->sh_size;
/* If this section fits in the segment we are constructing, add
it in. */
if ((file_offset - (p_offset + p_memsz)
== hdr->sh_addr - (p_vaddr + p_memsz))
&& (last_type != SHT_NOBITS || hdr->sh_type == SHT_NOBITS))
{
bfd_size_type adjust;
adjust = hdr->sh_addr - (p_vaddr + p_memsz);
p_memsz += hdr->sh_size + adjust;
file_offset = next_offset;
last_type = hdr->sh_type;
continue;
}
/* The section won't fit, start a new segment. */
++segs;
/* Initialize the segment. */
p_vaddr = hdr->sh_addr;
p_memsz = hdr->sh_size;
p_offset = file_offset;
file_offset = next_offset;
last_type = hdr->sh_type;
}
}
else
{
/* Assume we will need exactly two PT_LOAD segments: one for text
and one for data. */
segs = 2;
}
s = bfd_get_section_by_name (abfd, ".interp"); s = bfd_get_section_by_name (abfd, ".interp");
if (s != NULL && (s->flags & SEC_LOAD) != 0) if (s != NULL && (s->flags & SEC_LOAD) != 0)
@ -1750,7 +1854,8 @@ get_program_header_size (abfd)
++segs; ++segs;
} }
return segs * sizeof (Elf_External_Phdr); elf_tdata (abfd)->program_header_size = segs * sizeof (Elf_External_Phdr);
return elf_tdata (abfd)->program_header_size;
} }
/* Create the program header. OFF is the file offset where the /* Create the program header. OFF is the file offset where the
@ -1877,14 +1982,15 @@ map_program_segments (abfd, off, first, sorted_hdrs, phdr_size)
continue; continue;
} }
/* If we have a segment, move to the next one. */ /* The section won't fit, start a new segment. If we're already in one,
move to the next one. */
if (phdr->p_type != PT_NULL) if (phdr->p_type != PT_NULL)
{ {
++phdr; ++phdr;
++phdr_count; ++phdr_count;
} }
/* Start a new segment. */ /* Initialize the segment. */
phdr->p_type = PT_LOAD; phdr->p_type = PT_LOAD;
phdr->p_offset = hdr->sh_offset; phdr->p_offset = hdr->sh_offset;
phdr->p_vaddr = hdr->sh_addr; phdr->p_vaddr = hdr->sh_addr;
@ -2050,16 +2156,7 @@ assign_file_positions_except_relocs (abfd, dosyms)
Elf_Internal_Shdr *first; Elf_Internal_Shdr *first;
file_ptr phdr_map; file_ptr phdr_map;
/* We are creating an executable. We must create a program /* We are creating an executable. */
header. We can't actually create the program header until we
have set the file positions for the sections, but we can
figure out how big it is going to be. */
off = align_file_position (off);
phdr_size = get_program_header_size (abfd);
if (phdr_size == (file_ptr) -1)
return false;
phdr_off = off;
off += phdr_size;
maxpagesize = get_elf_backend_data (abfd)->maxpagesize; maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
if (maxpagesize == 0) if (maxpagesize == 0)
@ -2081,6 +2178,19 @@ assign_file_positions_except_relocs (abfd, dosyms)
qsort (sorted_hdrs, i_ehdrp->e_shnum - 1, sizeof (Elf_Internal_Shdr *), qsort (sorted_hdrs, i_ehdrp->e_shnum - 1, sizeof (Elf_Internal_Shdr *),
elf_sort_hdrs); elf_sort_hdrs);
/* We can't actually create the program header until we have set the
file positions for the sections, and we can't do that until we know
how big the header is going to be. */
off = align_file_position (off);
phdr_size = get_program_header_size (abfd,
sorted_hdrs, i_ehdrp->e_shnum - 1,
maxpagesize);
if (phdr_size == (file_ptr) -1)
return false;
/* Compute the file offsets of each section. */
phdr_off = off;
off += phdr_size;
first = NULL; first = NULL;
for (i = 1, hdrpp = sorted_hdrs; i < i_ehdrp->e_shnum; i++, hdrpp++) for (i = 1, hdrpp = sorted_hdrs; i < i_ehdrp->e_shnum; i++, hdrpp++)
{ {
@ -2116,6 +2226,7 @@ assign_file_positions_except_relocs (abfd, dosyms)
off = assign_file_position_for_section (hdr, off, false); off = assign_file_position_for_section (hdr, off, false);
} }
/* Create the program header. */
phdr_map = map_program_segments (abfd, phdr_off, first, sorted_hdrs, phdr_map = map_program_segments (abfd, phdr_off, first, sorted_hdrs,
phdr_size); phdr_size);
if (phdr_map == (file_ptr) -1) if (phdr_map == (file_ptr) -1)
@ -3209,7 +3320,8 @@ elf_sizeof_headers (abfd, reloc)
ret = sizeof (Elf_External_Ehdr); ret = sizeof (Elf_External_Ehdr);
if (! reloc) if (! reloc)
ret += get_program_header_size (abfd); ret += get_program_header_size (abfd, (Elf_Internal_Shdr **) NULL, 0,
(bfd_vma) 0);
return ret; return ret;
} }
@ -4297,7 +4409,8 @@ elf_link_add_object_symbols (abfd, info)
clobbering sec to be bfd_und_section_ptr. */ clobbering sec to be bfd_und_section_ptr. */
if (dynamic && definition) if (dynamic && definition)
{ {
if (h->root.type == bfd_link_hash_defined) if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
sec = bfd_und_section_ptr; sec = bfd_und_section_ptr;
} }
@ -4309,7 +4422,8 @@ elf_link_add_object_symbols (abfd, info)
object in the link. */ object in the link. */
if (! dynamic if (! dynamic
&& definition && definition
&& h->root.type == bfd_link_hash_defined && (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
&& (bfd_get_flavour (h->root.u.def.section->owner) && (bfd_get_flavour (h->root.u.def.section->owner)
== bfd_target_elf_flavour) == bfd_target_elf_flavour)
@ -4332,7 +4446,7 @@ elf_link_add_object_symbols (abfd, info)
&& ! bfd_is_und_section (sec) && ! bfd_is_und_section (sec)
&& (h->root.type == bfd_link_hash_new && (h->root.type == bfd_link_hash_new
|| h->root.type == bfd_link_hash_undefined || h->root.type == bfd_link_hash_undefined
|| h->root.type == bfd_link_hash_weak)) || h->root.type == bfd_link_hash_undefweak))
h->elf_link_hash_flags |= ELF_LINK_HASH_DEFINED_WEAK; h->elf_link_hash_flags |= ELF_LINK_HASH_DEFINED_WEAK;
} }
@ -4454,7 +4568,8 @@ elf_link_add_object_symbols (abfd, info)
weaks = hlook->weakdef; weaks = hlook->weakdef;
hlook->weakdef = NULL; hlook->weakdef = NULL;
BFD_ASSERT (hlook->root.type == bfd_link_hash_defined); BFD_ASSERT (hlook->root.type == bfd_link_hash_defined
|| hlook->root.type == bfd_link_hash_defweak);
slook = hlook->root.u.def.section; slook = hlook->root.u.def.section;
vlook = hlook->root.u.def.value; vlook = hlook->root.u.def.value;
@ -4466,7 +4581,8 @@ elf_link_add_object_symbols (abfd, info)
h = *hpp; h = *hpp;
if (h != hlook if (h != hlook
&& h->root.type == bfd_link_hash_defined && (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& h->root.u.def.section == slook && h->root.u.def.section == slook
&& h->root.u.def.value == vlook) && h->root.u.def.value == vlook)
{ {
@ -5136,9 +5252,11 @@ elf_adjust_dynamic_symbol (h, data)
{ {
struct elf_link_hash_entry *weakdef; struct elf_link_hash_entry *weakdef;
BFD_ASSERT (h->root.type == bfd_link_hash_defined); BFD_ASSERT (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak);
weakdef = h->weakdef; weakdef = h->weakdef;
BFD_ASSERT (weakdef->root.type == bfd_link_hash_defined); BFD_ASSERT (weakdef->root.type == bfd_link_hash_defined
|| weakdef->root.type == bfd_link_hash_defweak);
BFD_ASSERT (weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC); BFD_ASSERT (weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC);
if ((weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0) if ((weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
{ {
@ -5703,7 +5821,8 @@ elf_bfd_final_link (abfd, info)
h = elf_link_hash_lookup (elf_hash_table (info), name, h = elf_link_hash_lookup (elf_hash_table (info), name,
false, false, true); false, false, true);
BFD_ASSERT (h != NULL); BFD_ASSERT (h != NULL);
if (h->root.type == bfd_link_hash_defined) if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{ {
dyn.d_un.d_val = h->root.u.def.value; dyn.d_un.d_val = h->root.u.def.value;
o = h->root.u.def.section; o = h->root.u.def.section;
@ -5980,7 +6099,8 @@ elf_link_output_extsym (h, data)
sym.st_value = 0; sym.st_value = 0;
sym.st_size = h->size; sym.st_size = h->size;
sym.st_other = 0; sym.st_other = 0;
if (h->root.type == bfd_link_hash_weak if (h->root.type == bfd_link_hash_undefweak
|| h->root.type == bfd_link_hash_defweak
|| (h->elf_link_hash_flags & ELF_LINK_HASH_DEFINED_WEAK) != 0) || (h->elf_link_hash_flags & ELF_LINK_HASH_DEFINED_WEAK) != 0)
sym.st_info = ELF_ST_INFO (STB_WEAK, h->type); sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
else else
@ -5998,12 +6118,13 @@ elf_link_output_extsym (h, data)
sym.st_shndx = SHN_UNDEF; sym.st_shndx = SHN_UNDEF;
break; break;
case bfd_link_hash_weak: case bfd_link_hash_undefweak:
input_sec = bfd_und_section_ptr; input_sec = bfd_und_section_ptr;
sym.st_shndx = SHN_UNDEF; sym.st_shndx = SHN_UNDEF;
break; break;
case bfd_link_hash_defined: case bfd_link_hash_defined:
case bfd_link_hash_defweak:
{ {
input_sec = h->root.u.def.section; input_sec = h->root.u.def.section;
if (input_sec->output_section != NULL) if (input_sec->output_section != NULL)

View File

@ -342,7 +342,8 @@ linux_add_one_symbol (info, abfd, name, flags, section, value, string,
if (! info->relocateable if (! info->relocateable
&& linux_hash_table (info)->dynobj == NULL && linux_hash_table (info)->dynobj == NULL
&& strcmp (name, SHARABLE_CONFLICTS) == 0 && strcmp (name, SHARABLE_CONFLICTS) == 0
&& (flags & BSF_CONSTRUCTOR) != 0) && (flags & BSF_CONSTRUCTOR) != 0
&& abfd->xvec == info->hash->creator)
{ {
if (! linux_link_create_dynamic_sections (abfd, info)) if (! linux_link_create_dynamic_sections (abfd, info))
return false; return false;
@ -351,12 +352,13 @@ linux_add_one_symbol (info, abfd, name, flags, section, value, string,
} }
if (bfd_is_abs_section (section) if (bfd_is_abs_section (section)
&& (IS_GOT_SYM (name) || IS_PLT_SYM (name))) && abfd->xvec == info->hash->creator)
{ {
h = linux_link_hash_lookup (linux_hash_table (info), name, false, h = linux_link_hash_lookup (linux_hash_table (info), name, false,
false, false); false, false);
if (h != NULL if (h != NULL
&& h->root.root.type == bfd_link_hash_defined) && (h->root.root.type == bfd_link_hash_defined
|| h->root.root.type == bfd_link_hash_defweak))
{ {
struct fixup *f; struct fixup *f;
@ -445,7 +447,8 @@ linux_tally_symbols (h, data)
fixup anyway, since there are cases where these symbols come fixup anyway, since there are cases where these symbols come
from different shared libraries */ from different shared libraries */
if (h1 != NULL if (h1 != NULL
&& ((h1->root.root.type == bfd_link_hash_defined && (((h1->root.root.type == bfd_link_hash_defined
|| h1->root.root.type == bfd_link_hash_defweak)
&& ! bfd_is_abs_section (h1->root.root.u.def.section)) && ! bfd_is_abs_section (h1->root.root.u.def.section))
|| h2->root.root.type == bfd_link_hash_indirect)) || h2->root.root.type == bfd_link_hash_indirect))
{ {
@ -458,9 +461,11 @@ linux_tally_symbols (h, data)
f1 != NULL; f1 != NULL;
f1 = f1->next) f1 = f1->next)
{ {
if (f1->h != h if ((f1->h != h && f1->h != h1)
|| (! f1->builtin && ! f1->jump)) || (! f1->builtin && ! f1->jump))
continue; continue;
if (f1->h == h1)
exists = true;
if (! exists if (! exists
&& bfd_is_abs_section (h->root.root.u.def.section)) && bfd_is_abs_section (h->root.root.u.def.section))
{ {
@ -593,7 +598,8 @@ linux_finish_dynamic_link (output_bfd, info)
if (f->builtin) if (f->builtin)
continue; continue;
if (f->h->root.root.type != bfd_link_hash_defined) if (f->h->root.root.type != bfd_link_hash_defined
&& f->h->root.root.type != bfd_link_hash_defweak)
{ {
/* FIXME! */ /* FIXME! */
fprintf (stderr, fprintf (stderr,
@ -643,7 +649,8 @@ linux_finish_dynamic_link (output_bfd, info)
if (! f->builtin) if (! f->builtin)
continue; continue;
if (f->h->root.root.type != bfd_link_hash_defined) if (f->h->root.root.type != bfd_link_hash_defined
&& f->h->root.root.type != bfd_link_hash_defweak)
{ {
/* FIXME! */ /* FIXME! */
fprintf (stderr, fprintf (stderr,
@ -687,7 +694,9 @@ linux_finish_dynamic_link (output_bfd, info)
"__BUILTIN_FIXUPS__", "__BUILTIN_FIXUPS__",
false, false, false); false, false, false);
if (h != NULL && h->root.root.type == bfd_link_hash_defined) if (h != NULL
&& (h->root.root.type == bfd_link_hash_defined
|| h->root.root.type == bfd_link_hash_defweak))
{ {
is = h->root.root.u.def.section; is = h->root.root.u.def.section;
section_offset = is->output_section->vma + is->output_offset; section_offset = is->output_section->vma + is->output_offset;

View File

@ -308,12 +308,13 @@ struct elf_backend_data
referenced by a regular object. This is called after all the referenced by a regular object. This is called after all the
input files have been seen, but before the SIZE_DYNAMIC_SECTIONS input files have been seen, but before the SIZE_DYNAMIC_SECTIONS
function has been called. The hash table entry should be function has been called. The hash table entry should be
bfd_link_hash_defined, and it should be defined in a section from bfd_link_hash_defined ore bfd_link_hash_defweak, and it should be
a dynamic object. Dynamic object sections are not included in defined in a section from a dynamic object. Dynamic object
the final link, and this function is responsible for changing the sections are not included in the final link, and this function is
value to something which the rest of the link can deal with. responsible for changing the value to something which the rest of
This will normally involve adding an entry to the .plt or .got or the link can deal with. This will normally involve adding an
some such section, and setting the symbol to point to that. */ entry to the .plt or .got or some such section, and setting the
symbol to point to that. */
boolean (*elf_backend_adjust_dynamic_symbol) boolean (*elf_backend_adjust_dynamic_symbol)
PARAMS ((struct bfd_link_info *info, struct elf_link_hash_entry *h)); PARAMS ((struct bfd_link_info *info, struct elf_link_hash_entry *h));

View File

@ -1,5 +1,5 @@
/* linker.c -- BFD linker routines /* linker.c -- BFD linker routines
Copyright (C) 1993, 1994 Free Software Foundation, Inc. Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support
This file is part of BFD, the Binary File Descriptor library. This file is part of BFD, the Binary File Descriptor library.
@ -380,10 +380,7 @@ SUBSUBSECTION
written out when considering the symbols of each input file, written out when considering the symbols of each input file,
but it is still necessary to traverse the hash table since the but it is still necessary to traverse the hash table since the
linker script may have defined some symbols that are not in linker script may have defined some symbols that are not in
any of the input files. The <<written>> field in the any of the input files.
<<bfd_link_hash_entry>> structure may be used to determine
which entries in the hash table have not already been written
out.
The <<strip>> field of the <<bfd_link_info>> structure The <<strip>> field of the <<bfd_link_info>> structure
controls which symbols are written out. The possible values controls which symbols are written out. The possible values
@ -1065,9 +1062,9 @@ generic_link_check_archive_element (abfd, info, pneeded, collect)
/* We are only interested if we know something about this /* We are only interested if we know something about this
symbol, and it is undefined or common. An undefined weak symbol, and it is undefined or common. An undefined weak
symbol (type bfd_link_hash_weak) is not considered to be a symbol (type bfd_link_hash_undefweak) is not considered to be
reference when pulling files out of an archive. See the SVR4 a reference when pulling files out of an archive. See the
ABI, p. 4-27. */ SVR4 ABI, p. 4-27. */
h = bfd_link_hash_lookup (info->hash, bfd_asymbol_name (p), false, h = bfd_link_hash_lookup (info->hash, bfd_asymbol_name (p), false,
false, true); false, true);
if (h == (struct bfd_link_hash_entry *) NULL if (h == (struct bfd_link_hash_entry *) NULL
@ -1287,6 +1284,7 @@ enum link_action
UND, /* Mark symbol undefined. */ UND, /* Mark symbol undefined. */
WEAK, /* Mark symbol weak undefined. */ WEAK, /* Mark symbol weak undefined. */
DEF, /* Mark symbol defined. */ DEF, /* Mark symbol defined. */
DEFW, /* Mark symbol weak defined. */
COM, /* Mark symbol common. */ COM, /* Mark symbol common. */
REF, /* Mark defined symbol referenced. */ REF, /* Mark defined symbol referenced. */
CREF, /* Possibly warn about common reference to defined symbol. */ CREF, /* Possibly warn about common reference to defined symbol. */
@ -1309,17 +1307,17 @@ enum link_action
/* The state table itself. The first index is a link_row and the /* The state table itself. The first index is a link_row and the
second index is a bfd_link_hash_type. */ second index is a bfd_link_hash_type. */
static const enum link_action link_action[8][7] = static const enum link_action link_action[8][8] =
{ {
/* current\prev new undef weak def com indr warn */ /* current\prev new undef undefw def defw com indr warn */
/* UNDEF_ROW */ {UND, NOACT, NOACT, REF, NOACT, REFC, WARNC }, /* UNDEF_ROW */ {UND, NOACT, NOACT, REF, REF, NOACT, REFC, WARNC },
/* UNDEFW_ROW */ {WEAK, WEAK, NOACT, REF, NOACT, REFC, WARNC }, /* UNDEFW_ROW */ {WEAK, WEAK, NOACT, REF, REF, NOACT, REFC, WARNC },
/* DEF_ROW */ {DEF, DEF, DEF, MDEF, CDEF, MDEF, CYCLE }, /* DEF_ROW */ {DEF, DEF, DEF, MDEF, DEF, CDEF, MDEF, CYCLE },
/* DEFW_ROW */ {DEF, DEF, DEF, NOACT, NOACT, NOACT, CYCLE }, /* DEFW_ROW */ {DEFW, DEFW, DEFW, NOACT, NOACT, NOACT, NOACT, CYCLE },
/* COMMON_ROW */ {COM, COM, COM, CREF, BIG, CREF, WARNC }, /* COMMON_ROW */ {COM, COM, COM, CREF, CREF, BIG, CREF, WARNC },
/* INDR_ROW */ {IND, IND, IND, MDEF, CIND, MIND, CYCLE }, /* INDR_ROW */ {IND, IND, IND, MDEF, IND, CIND, MIND, CYCLE },
/* WARN_ROW */ {MWARN, WARN, WARN, CWARN, WARN, CWARN, CYCLE }, /* WARN_ROW */ {MWARN, WARN, WARN, CWARN, CWARN, WARN, CWARN, CYCLE },
/* SET_ROW */ {SET, SET, SET, SET, SET, CYCLE, CYCLE } /* SET_ROW */ {SET, SET, SET, SET, SET, SET, CYCLE, CYCLE }
}; };
/* Most of the entries in the LINK_ACTION table are straightforward, /* Most of the entries in the LINK_ACTION table are straightforward,
@ -1453,7 +1451,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
case WEAK: case WEAK:
/* Make a new weak undefined symbol. */ /* Make a new weak undefined symbol. */
h->type = bfd_link_hash_weak; h->type = bfd_link_hash_undefweak;
h->u.undef.abfd = abfd; h->u.undef.abfd = abfd;
break; break;
@ -1468,50 +1466,69 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
return false; return false;
/* Fall through. */ /* Fall through. */
case DEF: case DEF:
/* Define a symbol. */ case DEFW:
h->type = bfd_link_hash_defined; {
h->u.def.section = section; enum bfd_link_order_type oldtype;
h->u.def.value = value;
/* If we have been asked to, we act like collect2 and /* Define a symbol. */
identify all functions that might be global constructors oldtype = h->type;
and destructors and pass them up in a callback. We only if (action == DEFW)
do this for certain object file types, since many object h->type = bfd_link_hash_defweak;
file types can handle this automatically. */ else
if (collect && name[0] == '_') h->type = bfd_link_hash_defined;
{ h->u.def.section = section;
const char *s; h->u.def.value = value;
/* A constructor or destructor name starts like this: /* If we have been asked to, we act like collect2 and
_+GLOBAL_[_.$][ID][_.$] identify all functions that might be global
where the first [_.$] and the second are the same constructors and destructors and pass them up in a
character (we accept any character there, in case a callback. We only do this for certain object file
new object file format comes along with even worse types, since many object file types can handle this
naming restrictions). */ automatically. */
if (collect && name[0] == '_')
{
const char *s;
/* A constructor or destructor name starts like this:
_+GLOBAL_[_.$][ID][_.$] where the first [_.$] and
the second are the same character (we accept any
character there, in case a new object file format
comes along with even worse naming restrictions). */
#define CONS_PREFIX "GLOBAL_" #define CONS_PREFIX "GLOBAL_"
#define CONS_PREFIX_LEN (sizeof CONS_PREFIX - 1) #define CONS_PREFIX_LEN (sizeof CONS_PREFIX - 1)
s = name + 1; s = name + 1;
while (*s == '_') while (*s == '_')
++s; ++s;
if (s[0] == 'G' if (s[0] == 'G'
&& strncmp (s, CONS_PREFIX, CONS_PREFIX_LEN - 1) == 0) && strncmp (s, CONS_PREFIX, CONS_PREFIX_LEN - 1) == 0)
{ {
char c; char c;
c = s[CONS_PREFIX_LEN + 1]; c = s[CONS_PREFIX_LEN + 1];
if ((c == 'I' || c == 'D') if ((c == 'I' || c == 'D')
&& s[CONS_PREFIX_LEN] == s[CONS_PREFIX_LEN + 2]) && s[CONS_PREFIX_LEN] == s[CONS_PREFIX_LEN + 2])
{ {
if (! ((*info->callbacks->constructor) /* If this is a definition of a symbol which
(info, was previously weakly defined, we are in
c == 'I' ? true : false, trouble. We have already added a
name, abfd, section, value))) constructor entry for the weak defined
return false; symbol, and now we are trying to add one
} for the new symbol. Fortunately, this case
} should never arise in practice. */
} if (oldtype == bfd_link_hash_defweak)
abort ();
if (! ((*info->callbacks->constructor)
(info,
c == 'I' ? true : false,
name, abfd, section, value)))
return false;
}
}
}
}
break; break;
@ -1602,7 +1619,8 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
was already defined. FIXME: It would nice if we could was already defined. FIXME: It would nice if we could
report the BFD which defined an indirect symbol, but we report the BFD which defined an indirect symbol, but we
don't have anywhere to store the information. */ don't have anywhere to store the information. */
if (h->type == bfd_link_hash_defined) if (h->type == bfd_link_hash_defined
|| h->type == bfd_link_hash_defweak)
obfd = h->u.def.section->owner; obfd = h->u.def.section->owner;
else else
obfd = NULL; obfd = NULL;
@ -1631,10 +1649,6 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
msec = h->u.def.section; msec = h->u.def.section;
mval = h->u.def.value; mval = h->u.def.value;
break; break;
case bfd_link_hash_common:
msec = bfd_com_section_ptr;
mval = h->u.c.size;
break;
case bfd_link_hash_indirect: case bfd_link_hash_indirect:
msec = bfd_ind_section_ptr; msec = bfd_ind_section_ptr;
mval = 0; mval = 0;
@ -1738,10 +1752,10 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
case CWARN: case CWARN:
/* Warn if this symbol has been referenced already, /* Warn if this symbol has been referenced already,
otherwise either add a warning or cycle. A symbol has otherwise add a warning. A symbol has been referenced if
been referenced if the next field is not NULL, or it is the next field is not NULL, or it is the tail of the
the tail of the undefined symbol list. The REF case undefined symbol list. The REF case above helps to
above helps to ensure this. */ ensure this. */
if (h->next != NULL || info->hash->undefs_tail == h) if (h->next != NULL || info->hash->undefs_tail == h)
{ {
if (! (*info->callbacks->warning) (info, string)) if (! (*info->callbacks->warning) (info, string))
@ -2037,12 +2051,19 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
case bfd_link_hash_new: case bfd_link_hash_new:
abort (); abort ();
case bfd_link_hash_undefined: case bfd_link_hash_undefined:
case bfd_link_hash_weak: break;
case bfd_link_hash_undefweak:
sym->flags |= BSF_WEAK;
break; break;
case bfd_link_hash_defined: case bfd_link_hash_defined:
sym->flags |= BSF_GLOBAL;
sym->value = h->root.u.def.value;
sym->section = h->root.u.def.section;
break;
case bfd_link_hash_defweak:
sym->flags |= BSF_WEAK;
sym->value = h->root.u.def.value; sym->value = h->root.u.def.value;
sym->section = h->root.u.def.section; sym->section = h->root.u.def.section;
sym->flags |= BSF_GLOBAL;
break; break;
case bfd_link_hash_common: case bfd_link_hash_common:
sym->value = h->root.u.c.size; sym->value = h->root.u.c.size;
@ -2160,7 +2181,7 @@ set_symbol_from_hash (sym, h)
sym->section = bfd_und_section_ptr; sym->section = bfd_und_section_ptr;
sym->value = 0; sym->value = 0;
break; break;
case bfd_link_hash_weak: case bfd_link_hash_undefweak:
sym->section = bfd_und_section_ptr; sym->section = bfd_und_section_ptr;
sym->value = 0; sym->value = 0;
sym->flags |= BSF_WEAK; sym->flags |= BSF_WEAK;
@ -2169,6 +2190,11 @@ set_symbol_from_hash (sym, h)
sym->section = h->u.def.section; sym->section = h->u.def.section;
sym->value = h->u.def.value; sym->value = h->u.def.value;
break; break;
case bfd_link_hash_defweak:
sym->flags |= BSF_WEAK;
sym->section = h->u.def.section;
sym->value = h->u.def.value;
break;
case bfd_link_hash_common: case bfd_link_hash_common:
sym->value = h->u.c.size; sym->value = h->u.c.size;
if (sym->section == NULL) if (sym->section == NULL)
@ -2263,7 +2289,7 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order)
r->address = link_order->offset; r->address = link_order->offset;
r->howto = bfd_reloc_type_lookup (abfd, link_order->u.reloc.p->reloc); r->howto = bfd_reloc_type_lookup (abfd, link_order->u.reloc.p->reloc);
if (r->howto == (const reloc_howto_type *) NULL) if (r->howto == 0)
{ {
bfd_set_error (bfd_error_bad_value); bfd_set_error (bfd_error_bad_value);
return false; return false;

View File

@ -1,5 +1,5 @@
/* BFD backend for SunOS binaries. /* BFD backend for SunOS binaries.
Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. Copyright (C) 1990, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
Written by Cygnus Support. Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library. This file is part of BFD, the Binary File Descriptor library.
@ -859,7 +859,8 @@ sunos_add_one_symbol (info, abfd, name, flags, section, value, string,
if (! bfd_is_und_section (section) if (! bfd_is_und_section (section)
&& h->root.root.type != bfd_link_hash_new && h->root.root.type != bfd_link_hash_new
&& h->root.root.type != bfd_link_hash_undefined) && h->root.root.type != bfd_link_hash_undefined
&& h->root.root.type != bfd_link_hash_defweak)
{ {
/* We are defining the symbol, and it is already defined. This /* We are defining the symbol, and it is already defined. This
is a potential multiple definition error. */ is a potential multiple definition error. */
@ -1297,9 +1298,10 @@ sunos_scan_std_relocs (info, abfd, sec, relocs, rel_size)
/* At this point common symbols have already been allocated, so /* At this point common symbols have already been allocated, so
we don't have to worry about them. We need to consider that we don't have to worry about them. We need to consider that
we may have already seen this symbol and marked it undefined; we may have already seen this symbol and marked it undefined;
if the symbols is really undefined, then SUNOS_DEF_DYNAMIC if the symbol is really undefined, then SUNOS_DEF_DYNAMIC
will be zero. */ will be zero. */
if (h->root.root.type != bfd_link_hash_defined if (h->root.root.type != bfd_link_hash_defined
&& h->root.root.type != bfd_link_hash_defweak
&& h->root.root.type != bfd_link_hash_undefined) && h->root.root.type != bfd_link_hash_undefined)
continue; continue;
@ -1308,7 +1310,8 @@ sunos_scan_std_relocs (info, abfd, sec, relocs, rel_size)
continue; continue;
BFD_ASSERT ((h->flags & SUNOS_REF_REGULAR) != 0); BFD_ASSERT ((h->flags & SUNOS_REF_REGULAR) != 0);
BFD_ASSERT (h->root.root.type == bfd_link_hash_defined BFD_ASSERT ((h->root.root.type == bfd_link_hash_defined
|| h->root.root.type == bfd_link_hash_defweak)
? (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0 ? (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0
: (h->root.root.u.undef.abfd->flags & DYNAMIC) != 0); : (h->root.root.u.undef.abfd->flags & DYNAMIC) != 0);
@ -1444,6 +1447,7 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
if the symbols is really undefined, then SUNOS_DEF_DYNAMIC if the symbols is really undefined, then SUNOS_DEF_DYNAMIC
will be zero. */ will be zero. */
if (h->root.root.type != bfd_link_hash_defined if (h->root.root.type != bfd_link_hash_defined
&& h->root.root.type != bfd_link_hash_defweak
&& h->root.root.type != bfd_link_hash_undefined) && h->root.root.type != bfd_link_hash_undefined)
continue; continue;
@ -1452,7 +1456,8 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
continue; continue;
BFD_ASSERT ((h->flags & SUNOS_REF_REGULAR) != 0); BFD_ASSERT ((h->flags & SUNOS_REF_REGULAR) != 0);
BFD_ASSERT (h->root.root.type == bfd_link_hash_defined BFD_ASSERT ((h->root.root.type == bfd_link_hash_defined
|| h->root.root.type == bfd_link_hash_defweak)
? (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0 ? (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0
: (h->root.root.u.undef.abfd->flags & DYNAMIC) != 0); : (h->root.root.u.undef.abfd->flags & DYNAMIC) != 0);
@ -1527,7 +1532,8 @@ sunos_scan_dynamic_symbol (h, data)
&& (h->flags & SUNOS_DEF_DYNAMIC) != 0 && (h->flags & SUNOS_DEF_DYNAMIC) != 0
&& (h->flags & SUNOS_REF_REGULAR) != 0) && (h->flags & SUNOS_REF_REGULAR) != 0)
{ {
if (h->root.root.type == bfd_link_hash_defined if ((h->root.root.type == bfd_link_hash_defined
|| h->root.root.type == bfd_link_hash_defweak)
&& ((h->root.root.u.def.section->owner->flags & DYNAMIC) != 0) && ((h->root.root.u.def.section->owner->flags & DYNAMIC) != 0)
&& h->root.root.u.def.section->output_section == NULL) && h->root.root.u.def.section->output_section == NULL)
{ {
@ -1665,6 +1671,7 @@ sunos_write_dynamic_symbol (output_bfd, info, harg)
val = 0; val = 0;
break; break;
case bfd_link_hash_defined: case bfd_link_hash_defined:
case bfd_link_hash_defweak:
{ {
asection *sec; asection *sec;
asection *output_section; asection *output_section;
@ -1682,13 +1689,22 @@ sunos_write_dynamic_symbol (output_bfd, info, harg)
else else
{ {
if (output_section == obj_textsec (output_bfd)) if (output_section == obj_textsec (output_bfd))
type = N_TEXT | N_EXT; type = (h->root.root.type == bfd_link_hash_defined
? N_TEXT
: N_WEAKT);
else if (output_section == obj_datasec (output_bfd)) else if (output_section == obj_datasec (output_bfd))
type = N_DATA | N_EXT; type = (h->root.root.type == bfd_link_hash_defined
? N_DATA
: N_WEAKD);
else if (output_section == obj_bsssec (output_bfd)) else if (output_section == obj_bsssec (output_bfd))
type = N_BSS | N_EXT; type = (h->root.root.type == bfd_link_hash_defined
? N_BSS
: N_WEAKB);
else else
type = N_ABS | N_EXT; type = (h->root.root.type == bfd_link_hash_defined
? N_ABS
: N_WEAKA);
type |= N_EXT;
val = (h->root.root.u.def.value val = (h->root.root.u.def.value
+ output_section->vma + output_section->vma
+ sec->output_offset); + sec->output_offset);
@ -1699,7 +1715,7 @@ sunos_write_dynamic_symbol (output_bfd, info, harg)
type = N_UNDF | N_EXT; type = N_UNDF | N_EXT;
val = h->root.root.u.c.size; val = h->root.root.u.c.size;
break; break;
case bfd_link_hash_weak: case bfd_link_hash_undefweak:
type = N_WEAKU; type = N_WEAKU;
val = 0; val = 0;
break; break;