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:
parent
ebc4ca90f9
commit
6c97aedf26
@ -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>
|
||||
|
||||
Changes from Bryan Ford, baford@schirf.cs.utah.edu:
|
||||
|
96
bfd/aoutx.h
96
bfd/aoutx.h
@ -562,35 +562,33 @@ NAME(aout,some_aout_object_p) (abfd, execp, callback_to_real_object_p)
|
||||
|
||||
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
|
||||
guess at whether the file is executable. If the entry point
|
||||
is within the text segment, assume it is. (This makes files
|
||||
executable even if their entry point address is 0, as long as
|
||||
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... */
|
||||
their text starts at zero.). */
|
||||
if ((execp->a_entry >= obj_textsec(abfd)->vma) &&
|
||||
(execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size))
|
||||
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 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
|
||||
&& (hresolve == (struct aout_link_hash_entry *) NULL
|
||||
|| (hresolve->root.type != bfd_link_hash_defined
|
||||
&& hresolve->root.type != bfd_link_hash_defweak
|
||||
&& hresolve->root.type != bfd_link_hash_common)))
|
||||
|| type == N_WARNING)
|
||||
{
|
||||
@ -3841,13 +3840,14 @@ aout_link_write_symbols (finfo, input_bfd)
|
||||
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 *output_section;
|
||||
|
||||
/* This case means a common symbol which was turned
|
||||
into a defined symbol. */
|
||||
/* This case usually means a common symbol which was
|
||||
turned into a defined symbol. */
|
||||
input_section = hresolve->root.u.def.section;
|
||||
output_section = input_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;
|
||||
|
||||
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))
|
||||
type |= N_DATA;
|
||||
type |= (hresolve->root.type == bfd_link_hash_defined
|
||||
? N_DATA
|
||||
: N_WEAKD);
|
||||
else if (output_section == obj_bsssec (output_bfd))
|
||||
type |= N_BSS;
|
||||
type |= (hresolve->root.type == bfd_link_hash_defined
|
||||
? N_BSS
|
||||
: N_WEAKB);
|
||||
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)
|
||||
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;
|
||||
type = N_WEAKU;
|
||||
@ -4030,6 +4038,7 @@ aout_link_write_other_symbol (h, data)
|
||||
val = 0;
|
||||
break;
|
||||
case bfd_link_hash_defined:
|
||||
case bfd_link_hash_defweak:
|
||||
{
|
||||
asection *sec;
|
||||
|
||||
@ -4037,13 +4046,14 @@ aout_link_write_other_symbol (h, data)
|
||||
BFD_ASSERT (bfd_is_abs_section (sec)
|
||||
|| sec->owner == 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))
|
||||
type = N_DATA | N_EXT;
|
||||
type = h->root.type == bfd_link_hash_defined ? N_DATA : N_WEAKD;
|
||||
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
|
||||
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
|
||||
+ sec->vma
|
||||
+ h->root.u.def.section->output_offset);
|
||||
@ -4053,7 +4063,7 @@ aout_link_write_other_symbol (h, data)
|
||||
type = N_UNDF | N_EXT;
|
||||
val = h->root.u.c.size;
|
||||
break;
|
||||
case bfd_link_hash_weak:
|
||||
case bfd_link_hash_undefweak:
|
||||
type = N_WEAKU;
|
||||
val = 0;
|
||||
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. */
|
||||
h = sym_hashes[r_index];
|
||||
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;
|
||||
|
||||
@ -4443,14 +4454,15 @@ aout_link_input_section_std (finfo, input_bfd, input_section, relocs,
|
||||
}
|
||||
|
||||
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
|
||||
+ h->root.u.def.section->output_section->vma
|
||||
+ h->root.u.def.section->output_offset);
|
||||
}
|
||||
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;
|
||||
else
|
||||
{
|
||||
@ -4606,7 +4618,8 @@ aout_link_input_section_ext (finfo, input_bfd, input_section, relocs,
|
||||
is what the native linker does. */
|
||||
h = sym_hashes[r_index];
|
||||
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;
|
||||
|
||||
@ -4761,14 +4774,15 @@ aout_link_input_section_ext (finfo, input_bfd, input_section, relocs,
|
||||
}
|
||||
|
||||
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
|
||||
+ h->root.u.def.section->output_section->vma
|
||||
+ h->root.u.def.section->output_offset);
|
||||
}
|
||||
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;
|
||||
else
|
||||
{
|
||||
|
@ -385,7 +385,8 @@ coff_a29k_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
}
|
||||
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;
|
||||
val = (h->root.u.def.value
|
||||
|
26
bfd/ecoff.c
26
bfd/ecoff.c
@ -1,5 +1,5 @@
|
||||
/* 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.
|
||||
Full support added by Ian Lance Taylor, ian@cygnus.com.
|
||||
|
||||
@ -1358,7 +1358,7 @@ ecoff_type_to_string (abfd, fdr, indx)
|
||||
} qualifiers[7];
|
||||
unsigned int basic_type;
|
||||
int i;
|
||||
static char buffer1[1024];
|
||||
char buffer1[1024];
|
||||
static char buffer2[1024];
|
||||
char *p1 = buffer1;
|
||||
char *p2 = buffer2;
|
||||
@ -2027,6 +2027,8 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
|
||||
FDR *fdr_hold;
|
||||
boolean stabs;
|
||||
|
||||
offset += section->vma;
|
||||
|
||||
/* If we're not in the .text section, we don't have any line
|
||||
numbers. */
|
||||
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
|
||||
address, which is relative to the FDR address, and are also
|
||||
stored in increasing memory order. */
|
||||
if (offset < fdr_ptr->adr)
|
||||
return false;
|
||||
offset -= fdr_ptr->adr;
|
||||
external_pdr_size = debug_swap->external_pdr_size;
|
||||
pdr_ptr = ((char *) debug_info->external_pdr
|
||||
+ fdr_ptr->ipdFirst * external_pdr_size);
|
||||
pdr_end = pdr_ptr + fdr_ptr->cpd * external_pdr_size;
|
||||
(*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 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)
|
||||
{
|
||||
(*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
|
||||
if (offset < pdr.adr)
|
||||
if (offset < pdr.adr - first_off)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3860,6 +3862,9 @@ ecoff_link_add_archive_symbols (abfd, info)
|
||||
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
@ -4360,7 +4365,8 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
|
||||
if (h->abfd == (bfd *) NULL
|
||||
|| (! bfd_is_und_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->esym = esym;
|
||||
@ -4732,7 +4738,8 @@ ecoff_link_write_external (h, data)
|
||||
h->esym.asym.value = 0;
|
||||
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;
|
||||
else
|
||||
{
|
||||
@ -4787,12 +4794,13 @@ ecoff_link_write_external (h, data)
|
||||
case bfd_link_hash_new:
|
||||
abort ();
|
||||
case bfd_link_hash_undefined:
|
||||
case bfd_link_hash_weak:
|
||||
case bfd_link_hash_undefweak:
|
||||
if (h->esym.asym.sc != scUndefined
|
||||
&& h->esym.asym.sc != scSUndefined)
|
||||
h->esym.asym.sc = scUndefined;
|
||||
break;
|
||||
case bfd_link_hash_defined:
|
||||
case bfd_link_hash_defweak:
|
||||
if (h->esym.asym.sc == scUndefined
|
||||
|| h->esym.asym.sc == scSUndefined)
|
||||
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.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);
|
||||
return false;
|
||||
|
185
bfd/elfcode.h
185
bfd/elfcode.h
@ -163,7 +163,10 @@ static file_ptr assign_file_position_for_section
|
||||
static boolean assign_file_positions_except_relocs PARAMS ((bfd *, boolean));
|
||||
static int elf_sort_hdrs PARAMS ((const PTR, const PTR));
|
||||
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
|
||||
PARAMS ((bfd *, file_ptr, Elf_Internal_Shdr *, Elf_Internal_Shdr **,
|
||||
bfd_size_type));
|
||||
@ -1719,20 +1722,121 @@ assign_file_position_for_section (i_shdrp, offset, align)
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* Get the size of the program header. This is called by the linker
|
||||
before any of the section VMA's are set, so it can't calculate the
|
||||
correct value for a strange memory layout. */
|
||||
/* Get the size of the program header.
|
||||
|
||||
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
|
||||
get_program_header_size (abfd)
|
||||
get_program_header_size (abfd, sorted_hdrs, count, maxpagesize)
|
||||
bfd *abfd;
|
||||
Elf_Internal_Shdr **sorted_hdrs;
|
||||
unsigned int count;
|
||||
bfd_vma maxpagesize;
|
||||
{
|
||||
size_t segs;
|
||||
asection *s;
|
||||
|
||||
/* Assume we will need exactly two PT_LOAD segments: one for text
|
||||
and one for data. */
|
||||
segs = 2;
|
||||
/* We can't return a different result each time we're called. */
|
||||
if (elf_tdata (abfd)->program_header_size != 0)
|
||||
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");
|
||||
if (s != NULL && (s->flags & SEC_LOAD) != 0)
|
||||
@ -1750,7 +1854,8 @@ get_program_header_size (abfd)
|
||||
++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
|
||||
@ -1877,14 +1982,15 @@ map_program_segments (abfd, off, first, sorted_hdrs, phdr_size)
|
||||
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)
|
||||
{
|
||||
++phdr;
|
||||
++phdr_count;
|
||||
}
|
||||
|
||||
/* Start a new segment. */
|
||||
/* Initialize the segment. */
|
||||
phdr->p_type = PT_LOAD;
|
||||
phdr->p_offset = hdr->sh_offset;
|
||||
phdr->p_vaddr = hdr->sh_addr;
|
||||
@ -2050,16 +2156,7 @@ assign_file_positions_except_relocs (abfd, dosyms)
|
||||
Elf_Internal_Shdr *first;
|
||||
file_ptr phdr_map;
|
||||
|
||||
/* We are creating an executable. We must create a program
|
||||
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;
|
||||
/* We are creating an executable. */
|
||||
|
||||
maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
|
||||
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 *),
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
/* Create the program header. */
|
||||
phdr_map = map_program_segments (abfd, phdr_off, first, sorted_hdrs,
|
||||
phdr_size);
|
||||
if (phdr_map == (file_ptr) -1)
|
||||
@ -3209,7 +3320,8 @@ elf_sizeof_headers (abfd, reloc)
|
||||
|
||||
ret = sizeof (Elf_External_Ehdr);
|
||||
if (! reloc)
|
||||
ret += get_program_header_size (abfd);
|
||||
ret += get_program_header_size (abfd, (Elf_Internal_Shdr **) NULL, 0,
|
||||
(bfd_vma) 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -4297,7 +4409,8 @@ elf_link_add_object_symbols (abfd, info)
|
||||
clobbering sec to be bfd_und_section_ptr. */
|
||||
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;
|
||||
}
|
||||
|
||||
@ -4309,7 +4422,8 @@ elf_link_add_object_symbols (abfd, info)
|
||||
object in the link. */
|
||||
if (! dynamic
|
||||
&& 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
|
||||
&& (bfd_get_flavour (h->root.u.def.section->owner)
|
||||
== bfd_target_elf_flavour)
|
||||
@ -4332,7 +4446,7 @@ elf_link_add_object_symbols (abfd, info)
|
||||
&& ! bfd_is_und_section (sec)
|
||||
&& (h->root.type == bfd_link_hash_new
|
||||
|| 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;
|
||||
}
|
||||
|
||||
@ -4454,7 +4568,8 @@ elf_link_add_object_symbols (abfd, info)
|
||||
weaks = hlook->weakdef;
|
||||
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;
|
||||
vlook = hlook->root.u.def.value;
|
||||
|
||||
@ -4466,7 +4581,8 @@ elf_link_add_object_symbols (abfd, info)
|
||||
|
||||
h = *hpp;
|
||||
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.value == vlook)
|
||||
{
|
||||
@ -5136,9 +5252,11 @@ elf_adjust_dynamic_symbol (h, data)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
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,
|
||||
false, false, true);
|
||||
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;
|
||||
o = h->root.u.def.section;
|
||||
@ -5980,7 +6099,8 @@ elf_link_output_extsym (h, data)
|
||||
sym.st_value = 0;
|
||||
sym.st_size = h->size;
|
||||
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)
|
||||
sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
|
||||
else
|
||||
@ -5998,12 +6118,13 @@ elf_link_output_extsym (h, data)
|
||||
sym.st_shndx = SHN_UNDEF;
|
||||
break;
|
||||
|
||||
case bfd_link_hash_weak:
|
||||
case bfd_link_hash_undefweak:
|
||||
input_sec = bfd_und_section_ptr;
|
||||
sym.st_shndx = SHN_UNDEF;
|
||||
break;
|
||||
|
||||
case bfd_link_hash_defined:
|
||||
case bfd_link_hash_defweak:
|
||||
{
|
||||
input_sec = h->root.u.def.section;
|
||||
if (input_sec->output_section != NULL)
|
||||
|
@ -342,7 +342,8 @@ linux_add_one_symbol (info, abfd, name, flags, section, value, string,
|
||||
if (! info->relocateable
|
||||
&& linux_hash_table (info)->dynobj == NULL
|
||||
&& 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))
|
||||
return false;
|
||||
@ -351,12 +352,13 @@ linux_add_one_symbol (info, abfd, name, flags, section, value, string,
|
||||
}
|
||||
|
||||
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,
|
||||
false, false);
|
||||
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;
|
||||
|
||||
@ -445,7 +447,8 @@ linux_tally_symbols (h, data)
|
||||
fixup anyway, since there are cases where these symbols come
|
||||
from different shared libraries */
|
||||
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))
|
||||
|| h2->root.root.type == bfd_link_hash_indirect))
|
||||
{
|
||||
@ -458,9 +461,11 @@ linux_tally_symbols (h, data)
|
||||
f1 != NULL;
|
||||
f1 = f1->next)
|
||||
{
|
||||
if (f1->h != h
|
||||
if ((f1->h != h && f1->h != h1)
|
||||
|| (! f1->builtin && ! f1->jump))
|
||||
continue;
|
||||
if (f1->h == h1)
|
||||
exists = true;
|
||||
if (! exists
|
||||
&& bfd_is_abs_section (h->root.root.u.def.section))
|
||||
{
|
||||
@ -593,7 +598,8 @@ linux_finish_dynamic_link (output_bfd, info)
|
||||
if (f->builtin)
|
||||
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! */
|
||||
fprintf (stderr,
|
||||
@ -643,7 +649,8 @@ linux_finish_dynamic_link (output_bfd, info)
|
||||
if (! f->builtin)
|
||||
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! */
|
||||
fprintf (stderr,
|
||||
@ -687,7 +694,9 @@ linux_finish_dynamic_link (output_bfd, info)
|
||||
"__BUILTIN_FIXUPS__",
|
||||
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;
|
||||
section_offset = is->output_section->vma + is->output_offset;
|
||||
|
13
bfd/libelf.h
13
bfd/libelf.h
@ -308,12 +308,13 @@ struct elf_backend_data
|
||||
referenced by a regular object. This is called after all the
|
||||
input files have been seen, but before the SIZE_DYNAMIC_SECTIONS
|
||||
function has been called. The hash table entry should be
|
||||
bfd_link_hash_defined, and it should be defined in a section from
|
||||
a dynamic object. Dynamic object sections are not included in
|
||||
the final link, and this function is responsible for changing the
|
||||
value to something which the rest of the link can deal with.
|
||||
This will normally involve adding an entry to the .plt or .got or
|
||||
some such section, and setting the symbol to point to that. */
|
||||
bfd_link_hash_defined ore bfd_link_hash_defweak, and it should be
|
||||
defined in a section from a dynamic object. Dynamic object
|
||||
sections are not included in the final link, and this function is
|
||||
responsible for changing the value to something which the rest of
|
||||
the link can deal with. This will normally involve adding an
|
||||
entry to the .plt or .got or some such section, and setting the
|
||||
symbol to point to that. */
|
||||
boolean (*elf_backend_adjust_dynamic_symbol)
|
||||
PARAMS ((struct bfd_link_info *info, struct elf_link_hash_entry *h));
|
||||
|
||||
|
164
bfd/linker.c
164
bfd/linker.c
@ -1,5 +1,5 @@
|
||||
/* 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
|
||||
|
||||
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,
|
||||
but it is still necessary to traverse the hash table since the
|
||||
linker script may have defined some symbols that are not in
|
||||
any of the input files. The <<written>> field in the
|
||||
<<bfd_link_hash_entry>> structure may be used to determine
|
||||
which entries in the hash table have not already been written
|
||||
out.
|
||||
any of the input files.
|
||||
|
||||
The <<strip>> field of the <<bfd_link_info>> structure
|
||||
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
|
||||
symbol, and it is undefined or common. An undefined weak
|
||||
symbol (type bfd_link_hash_weak) is not considered to be a
|
||||
reference when pulling files out of an archive. See the SVR4
|
||||
ABI, p. 4-27. */
|
||||
symbol (type bfd_link_hash_undefweak) is not considered to be
|
||||
a reference when pulling files out of an archive. See the
|
||||
SVR4 ABI, p. 4-27. */
|
||||
h = bfd_link_hash_lookup (info->hash, bfd_asymbol_name (p), false,
|
||||
false, true);
|
||||
if (h == (struct bfd_link_hash_entry *) NULL
|
||||
@ -1287,6 +1284,7 @@ enum link_action
|
||||
UND, /* Mark symbol undefined. */
|
||||
WEAK, /* Mark symbol weak undefined. */
|
||||
DEF, /* Mark symbol defined. */
|
||||
DEFW, /* Mark symbol weak defined. */
|
||||
COM, /* Mark symbol common. */
|
||||
REF, /* Mark defined symbol referenced. */
|
||||
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
|
||||
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 */
|
||||
/* UNDEF_ROW */ {UND, NOACT, NOACT, REF, NOACT, REFC, WARNC },
|
||||
/* UNDEFW_ROW */ {WEAK, WEAK, NOACT, REF, NOACT, REFC, WARNC },
|
||||
/* DEF_ROW */ {DEF, DEF, DEF, MDEF, CDEF, MDEF, CYCLE },
|
||||
/* DEFW_ROW */ {DEF, DEF, DEF, NOACT, NOACT, NOACT, CYCLE },
|
||||
/* COMMON_ROW */ {COM, COM, COM, CREF, BIG, CREF, WARNC },
|
||||
/* INDR_ROW */ {IND, IND, IND, MDEF, CIND, MIND, CYCLE },
|
||||
/* WARN_ROW */ {MWARN, WARN, WARN, CWARN, WARN, CWARN, CYCLE },
|
||||
/* SET_ROW */ {SET, SET, SET, SET, SET, CYCLE, CYCLE }
|
||||
/* current\prev new undef undefw def defw com indr warn */
|
||||
/* UNDEF_ROW */ {UND, NOACT, NOACT, REF, REF, NOACT, REFC, WARNC },
|
||||
/* UNDEFW_ROW */ {WEAK, WEAK, NOACT, REF, REF, NOACT, REFC, WARNC },
|
||||
/* DEF_ROW */ {DEF, DEF, DEF, MDEF, DEF, CDEF, MDEF, CYCLE },
|
||||
/* DEFW_ROW */ {DEFW, DEFW, DEFW, NOACT, NOACT, NOACT, NOACT, CYCLE },
|
||||
/* COMMON_ROW */ {COM, COM, COM, CREF, CREF, BIG, CREF, WARNC },
|
||||
/* INDR_ROW */ {IND, IND, IND, MDEF, IND, CIND, MIND, CYCLE },
|
||||
/* WARN_ROW */ {MWARN, WARN, WARN, CWARN, CWARN, WARN, CWARN, CYCLE },
|
||||
/* SET_ROW */ {SET, SET, SET, SET, SET, SET, CYCLE, CYCLE }
|
||||
};
|
||||
|
||||
/* 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:
|
||||
/* Make a new weak undefined symbol. */
|
||||
h->type = bfd_link_hash_weak;
|
||||
h->type = bfd_link_hash_undefweak;
|
||||
h->u.undef.abfd = abfd;
|
||||
break;
|
||||
|
||||
@ -1468,50 +1466,69 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
|
||||
return false;
|
||||
/* Fall through. */
|
||||
case DEF:
|
||||
/* Define a symbol. */
|
||||
h->type = bfd_link_hash_defined;
|
||||
h->u.def.section = section;
|
||||
h->u.def.value = value;
|
||||
case DEFW:
|
||||
{
|
||||
enum bfd_link_order_type oldtype;
|
||||
|
||||
/* If we have been asked to, we act like collect2 and
|
||||
identify all functions that might be global constructors
|
||||
and destructors and pass them up in a callback. We only
|
||||
do this for certain object file types, since many object
|
||||
file types can handle this automatically. */
|
||||
if (collect && name[0] == '_')
|
||||
{
|
||||
const char *s;
|
||||
/* Define a symbol. */
|
||||
oldtype = h->type;
|
||||
if (action == DEFW)
|
||||
h->type = bfd_link_hash_defweak;
|
||||
else
|
||||
h->type = bfd_link_hash_defined;
|
||||
h->u.def.section = section;
|
||||
h->u.def.value = value;
|
||||
|
||||
/* 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). */
|
||||
/* If we have been asked to, we act like collect2 and
|
||||
identify all functions that might be global
|
||||
constructors and destructors and pass them up in a
|
||||
callback. We only do this for certain object file
|
||||
types, since many object file types can handle this
|
||||
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_LEN (sizeof CONS_PREFIX - 1)
|
||||
|
||||
s = name + 1;
|
||||
while (*s == '_')
|
||||
++s;
|
||||
if (s[0] == 'G'
|
||||
&& strncmp (s, CONS_PREFIX, CONS_PREFIX_LEN - 1) == 0)
|
||||
{
|
||||
char c;
|
||||
s = name + 1;
|
||||
while (*s == '_')
|
||||
++s;
|
||||
if (s[0] == 'G'
|
||||
&& strncmp (s, CONS_PREFIX, CONS_PREFIX_LEN - 1) == 0)
|
||||
{
|
||||
char c;
|
||||
|
||||
c = s[CONS_PREFIX_LEN + 1];
|
||||
if ((c == 'I' || c == 'D')
|
||||
&& s[CONS_PREFIX_LEN] == s[CONS_PREFIX_LEN + 2])
|
||||
{
|
||||
if (! ((*info->callbacks->constructor)
|
||||
(info,
|
||||
c == 'I' ? true : false,
|
||||
name, abfd, section, value)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
c = s[CONS_PREFIX_LEN + 1];
|
||||
if ((c == 'I' || c == 'D')
|
||||
&& s[CONS_PREFIX_LEN] == s[CONS_PREFIX_LEN + 2])
|
||||
{
|
||||
/* If this is a definition of a symbol which
|
||||
was previously weakly defined, we are in
|
||||
trouble. We have already added a
|
||||
constructor entry for the weak defined
|
||||
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;
|
||||
|
||||
@ -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
|
||||
report the BFD which defined an indirect symbol, but we
|
||||
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;
|
||||
else
|
||||
obfd = NULL;
|
||||
@ -1631,10 +1649,6 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
|
||||
msec = h->u.def.section;
|
||||
mval = h->u.def.value;
|
||||
break;
|
||||
case bfd_link_hash_common:
|
||||
msec = bfd_com_section_ptr;
|
||||
mval = h->u.c.size;
|
||||
break;
|
||||
case bfd_link_hash_indirect:
|
||||
msec = bfd_ind_section_ptr;
|
||||
mval = 0;
|
||||
@ -1738,10 +1752,10 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
|
||||
|
||||
case CWARN:
|
||||
/* Warn if this symbol has been referenced already,
|
||||
otherwise either add a warning or cycle. A symbol has
|
||||
been referenced if the next field is not NULL, or it is
|
||||
the tail of the undefined symbol list. The REF case
|
||||
above helps to ensure this. */
|
||||
otherwise add a warning. A symbol has been referenced if
|
||||
the next field is not NULL, or it is the tail of the
|
||||
undefined symbol list. The REF case above helps to
|
||||
ensure this. */
|
||||
if (h->next != NULL || info->hash->undefs_tail == h)
|
||||
{
|
||||
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:
|
||||
abort ();
|
||||
case bfd_link_hash_undefined:
|
||||
case bfd_link_hash_weak:
|
||||
break;
|
||||
case bfd_link_hash_undefweak:
|
||||
sym->flags |= BSF_WEAK;
|
||||
break;
|
||||
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->section = h->root.u.def.section;
|
||||
sym->flags |= BSF_GLOBAL;
|
||||
break;
|
||||
case bfd_link_hash_common:
|
||||
sym->value = h->root.u.c.size;
|
||||
@ -2160,7 +2181,7 @@ set_symbol_from_hash (sym, h)
|
||||
sym->section = bfd_und_section_ptr;
|
||||
sym->value = 0;
|
||||
break;
|
||||
case bfd_link_hash_weak:
|
||||
case bfd_link_hash_undefweak:
|
||||
sym->section = bfd_und_section_ptr;
|
||||
sym->value = 0;
|
||||
sym->flags |= BSF_WEAK;
|
||||
@ -2169,6 +2190,11 @@ set_symbol_from_hash (sym, h)
|
||||
sym->section = h->u.def.section;
|
||||
sym->value = h->u.def.value;
|
||||
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:
|
||||
sym->value = h->u.c.size;
|
||||
if (sym->section == NULL)
|
||||
@ -2263,7 +2289,7 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order)
|
||||
|
||||
r->address = link_order->offset;
|
||||
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);
|
||||
return false;
|
||||
|
38
bfd/sunos.c
38
bfd/sunos.c
@ -1,5 +1,5 @@
|
||||
/* 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.
|
||||
|
||||
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)
|
||||
&& 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
|
||||
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
|
||||
we don't have to worry about them. We need to consider that
|
||||
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. */
|
||||
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)
|
||||
continue;
|
||||
|
||||
@ -1308,7 +1310,8 @@ sunos_scan_std_relocs (info, abfd, sec, relocs, rel_size)
|
||||
continue;
|
||||
|
||||
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.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
|
||||
will be zero. */
|
||||
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)
|
||||
continue;
|
||||
|
||||
@ -1452,7 +1456,8 @@ sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
|
||||
continue;
|
||||
|
||||
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.undef.abfd->flags & DYNAMIC) != 0);
|
||||
|
||||
@ -1527,7 +1532,8 @@ sunos_scan_dynamic_symbol (h, data)
|
||||
&& (h->flags & SUNOS_DEF_DYNAMIC) != 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->output_section == NULL)
|
||||
{
|
||||
@ -1665,6 +1671,7 @@ sunos_write_dynamic_symbol (output_bfd, info, harg)
|
||||
val = 0;
|
||||
break;
|
||||
case bfd_link_hash_defined:
|
||||
case bfd_link_hash_defweak:
|
||||
{
|
||||
asection *sec;
|
||||
asection *output_section;
|
||||
@ -1682,13 +1689,22 @@ sunos_write_dynamic_symbol (output_bfd, info, harg)
|
||||
else
|
||||
{
|
||||
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))
|
||||
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))
|
||||
type = N_BSS | N_EXT;
|
||||
type = (h->root.root.type == bfd_link_hash_defined
|
||||
? N_BSS
|
||||
: N_WEAKB);
|
||||
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
|
||||
+ output_section->vma
|
||||
+ sec->output_offset);
|
||||
@ -1699,7 +1715,7 @@ sunos_write_dynamic_symbol (output_bfd, info, harg)
|
||||
type = N_UNDF | N_EXT;
|
||||
val = h->root.root.u.c.size;
|
||||
break;
|
||||
case bfd_link_hash_weak:
|
||||
case bfd_link_hash_undefweak:
|
||||
type = N_WEAKU;
|
||||
val = 0;
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user