From 6c97aedf2686633d3e837802ce51ebe630f64056 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 6 Feb 1995 20:01:08 +0000 Subject: [PATCH] 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. --- bfd/ChangeLog | 50 +++++++++++++ bfd/aoutx.h | 96 ++++++++++++++----------- bfd/coff-a29k.c | 3 +- bfd/ecoff.c | 26 ++++--- bfd/elfcode.h | 185 +++++++++++++++++++++++++++++++++++++++--------- bfd/i386linux.c | 25 ++++--- bfd/libelf.h | 13 ++-- bfd/linker.c | 168 ++++++++++++++++++++++++------------------- bfd/sunos.c | 38 +++++++--- 9 files changed, 425 insertions(+), 179 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 3b9df307a29..0b3194bf20d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,53 @@ +Mon Feb 6 14:25:24 1995 Ian Lance Taylor + + 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 Changes from Bryan Ford, baford@schirf.cs.utah.edu: diff --git a/bfd/aoutx.h b/bfd/aoutx.h index cad9d348143..19a7de18d7c 100644 --- a/bfd/aoutx.h +++ b/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 { diff --git a/bfd/coff-a29k.c b/bfd/coff-a29k.c index 7eeb6bd21b2..35c748a9564 100644 --- a/bfd/coff-a29k.c +++ b/bfd/coff-a29k.c @@ -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 diff --git a/bfd/ecoff.c b/bfd/ecoff.c index 0875a95d400..d6fbea93581 100644 --- a/bfd/ecoff.c +++ b/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; diff --git a/bfd/elfcode.h b/bfd/elfcode.h index 2edd5a8f5ef..0e61bb3c881 100644 --- a/bfd/elfcode.h +++ b/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) diff --git a/bfd/i386linux.c b/bfd/i386linux.c index 7bd67ca9c39..91d41430d60 100644 --- a/bfd/i386linux.c +++ b/bfd/i386linux.c @@ -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; diff --git a/bfd/libelf.h b/bfd/libelf.h index 262007767ff..d732bef20dc 100644 --- a/bfd/libelf.h +++ b/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)); diff --git a/bfd/linker.c b/bfd/linker.c index 37ab1c8e270..1c4b8fe73cf 100644 --- a/bfd/linker.c +++ b/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 <> field in the - <> structure may be used to determine - which entries in the hash table have not already been written - out. + any of the input files. The <> field of the <> 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; - - /* 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; @@ -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; diff --git a/bfd/sunos.c b/bfd/sunos.c index 157eba97a17..427beb4d188 100644 --- a/bfd/sunos.c +++ b/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; -- 2.30.2