* 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 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:
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. */
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)
{
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)
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;
val = 0;
break;
case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
{
asection *sec;
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);
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:
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;
}
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
{
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;
}
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
{
}
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
/* 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.
} 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;
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
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. */
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;
}
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;
}
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;
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
{
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;
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;
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));
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)
++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
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;
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)
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++)
{
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)
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;
}
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;
}
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)
&& ! 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;
}
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;
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)
{
{
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)
{
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;
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
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)
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;
}
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;
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))
{
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))
{
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,
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,
"__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;
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));
/* 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.
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
/* 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
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. */
/* 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,
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;
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;
-
- /* 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;
+ case DEFW:
+ {
+ enum bfd_link_order_type oldtype;
- /* 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 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;
+
+ /* 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;
-
- 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;
- }
- }
- }
+ 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 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;
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;
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;
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))
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;
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;
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)
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;
/* 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.
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. */
/* 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;
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);
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;
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);
&& (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)
{
val = 0;
break;
case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
{
asection *sec;
asection *output_section;
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);
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;