X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felflink.h;h=dd5b4db72637be11cdedeb8c1889fc4d7f7163c9;hb=258b1f5d18105cada68ce457610e1e4614a568d6;hp=4ef3c8b3c49b84576c6c3fe600b4d53066551c17;hpb=8881b321e06d93be5b37a5504359347b0e104bf0;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elflink.h b/bfd/elflink.h index 4ef3c8b3c4..dd5b4db726 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -1,5 +1,5 @@ /* ELF linker support. - Copyright 1995, 1996 Free Software Foundation, Inc. + Copyright 1995, 1996, 1997 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -23,8 +23,6 @@ static boolean elf_link_add_object_symbols PARAMS ((bfd *, struct bfd_link_info *)); static boolean elf_link_add_archive_symbols PARAMS ((bfd *, struct bfd_link_info *)); -static Elf_Internal_Rela *elf_link_read_relocs - PARAMS ((bfd *, asection *, PTR, Elf_Internal_Rela *, boolean)); static boolean elf_export_symbol PARAMS ((struct elf_link_hash_entry *, PTR)); static boolean elf_adjust_dynamic_symbol @@ -37,7 +35,7 @@ struct elf_info_failed { boolean failed; struct bfd_link_info *info; -}; +}; /* Given an ELF BFD, add symbols to the global hash table as appropriate. */ @@ -283,7 +281,7 @@ elf_link_add_object_symbols (abfd, info) goto error_return; if (! (_bfd_generic_link_add_one_symbol - (info, abfd, + (info, abfd, name + sizeof ".gnu.warning." - 1, BSF_WARNING, s, (bfd_vma) 0, msg, false, collect, (struct bfd_link_hash_entry **) NULL))) @@ -679,17 +677,25 @@ elf_link_add_object_symbols (abfd, info) by some other object. If it has, we want to use the existing definition, and we do not want to report a multiple symbol definition error; we do this by - clobbering sec to be bfd_und_section_ptr. */ + clobbering sec to be bfd_und_section_ptr. We treat a + common symbol as a definition if the symbol in the shared + library is a function, since common symbols always + represent variables; this can cause confusion in + principle, but any such confusion would seem to indicate + an erroneous program or shared library. */ if (dynamic && definition) { if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak || (h->root.type == bfd_link_hash_common - && bind == STB_WEAK)) + && (bind == STB_WEAK + || ELF_ST_TYPE (sym.st_info) == STT_FUNC))) { sec = bfd_und_section_ptr; definition = false; size_change_ok = true; + if (h->root.type == bfd_link_hash_common) + type_change_ok = true; } } @@ -700,7 +706,10 @@ elf_link_add_object_symbols (abfd, info) objects, even if they are defined after the dynamic object in the link. */ if (! dynamic - && definition + && (definition + || (bfd_is_com_section (sec) + && (h->root.type == bfd_link_hash_defweak + || h->type == STT_FUNC))) && (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 @@ -715,6 +724,8 @@ elf_link_add_object_symbols (abfd, info) h->root.type = bfd_link_hash_undefined; h->root.u.undef.abfd = h->root.u.def.section->owner; size_change_ok = true; + if (bfd_is_com_section (sec)) + type_change_ok = true; } } @@ -791,12 +802,15 @@ elf_link_add_object_symbols (abfd, info) h->type = ELF_ST_TYPE (sym.st_info); } + if (sym.st_other != 0 + && (definition || h->other == 0)) + h->other = sym.st_other; + /* Set a flag in the hash table entry indicating the type of reference or definition we just found. Keep a count of the number of dynamic symbols we find. A dynamic symbol is one which is referenced or defined by both a regular - object and a shared object, or one which is referenced or - defined by more than one shared object. */ + object and a shared object. */ old_flags = h->elf_link_hash_flags; dynsym = false; if (! dynamic) @@ -816,12 +830,11 @@ elf_link_add_object_symbols (abfd, info) new_flag = ELF_LINK_HASH_REF_DYNAMIC; else new_flag = ELF_LINK_HASH_DEF_DYNAMIC; - if ((old_flags & new_flag) != 0 - || (old_flags & (ELF_LINK_HASH_DEF_REGULAR - | ELF_LINK_HASH_REF_REGULAR)) != 0 + if ((old_flags & (ELF_LINK_HASH_DEF_REGULAR + | ELF_LINK_HASH_REF_REGULAR)) != 0 || (h->weakdef != NULL - && (old_flags & (ELF_LINK_HASH_DEF_DYNAMIC - | ELF_LINK_HASH_REF_DYNAMIC)) != 0)) + && ! new_weakdef + && h->weakdef->dynindx != -1)) dynsym = true; } @@ -898,6 +911,18 @@ elf_link_add_object_symbols (abfd, info) goto error_return; } + /* If the real definition is in the list of dynamic + symbols, make sure the weak definition is put there + as well. If we don't do this, then the dynamic + loader might not merge the entries for the real + definition and the weak definition. */ + if (h->dynindx != -1 + && hlook->dynindx == -1) + { + if (! _bfd_elf_link_record_dynamic_symbol (info, hlook)) + goto error_return; + } + break; } } @@ -942,15 +967,10 @@ elf_link_add_object_symbols (abfd, info) || o->reloc_count == 0) continue; - /* I believe we can ignore the relocs for any section which - does not form part of the final process image, such as a - debugging section. */ - if ((o->flags & SEC_ALLOC) == 0) - continue; - - internal_relocs = elf_link_read_relocs (abfd, o, (PTR) NULL, - (Elf_Internal_Rela *) NULL, - info->keep_memory); + internal_relocs = (NAME(_bfd_elf,link_read_relocs) + (abfd, o, (PTR) NULL, + (Elf_Internal_Rela *) NULL, + info->keep_memory)); if (internal_relocs == NULL) goto error_return; @@ -964,6 +984,35 @@ elf_link_add_object_symbols (abfd, info) } } + /* If this is a non-traditional, non-relocateable link, try to + optimize the handling of the .stab/.stabstr sections. */ + if (! dynamic + && ! info->relocateable + && ! info->traditional_format + && info->hash->creator->flavour == bfd_target_elf_flavour + && (info->strip != strip_all && info->strip != strip_debugger)) + { + asection *stab, *stabstr; + + stab = bfd_get_section_by_name (abfd, ".stab"); + if (stab != NULL) + { + stabstr = bfd_get_section_by_name (abfd, ".stabstr"); + + if (stabstr != NULL) + { + struct bfd_elf_section_data *secdata; + + secdata = elf_section_data (stab); + if (! _bfd_link_section_stabs (abfd, + &elf_hash_table (info)->stab_info, + stab, stabstr, + &secdata->stab_info)) + goto error_return; + } + } + } + return true; error_return: @@ -1002,7 +1051,8 @@ elf_link_create_dynamic_sections (abfd, info) /* Note that we set the SEC_IN_MEMORY flag for all of these sections. */ - flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY; + flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS + | SEC_IN_MEMORY | SEC_LINKER_CREATED); /* A dynamically linked executable has a .interp section, but a shared library does not. */ @@ -1121,8 +1171,9 @@ elf_add_dynamic_entry (info, tag, val) value is allocated using either malloc or bfd_alloc, according to the KEEP_MEMORY argument. */ -static Elf_Internal_Rela * -elf_link_read_relocs (abfd, o, external_relocs, internal_relocs, keep_memory) +Elf_Internal_Rela * +NAME(_bfd_elf,link_read_relocs) (abfd, o, external_relocs, internal_relocs, + keep_memory) bfd *abfd; asection *o; PTR external_relocs; @@ -1207,7 +1258,7 @@ elf_link_read_relocs (abfd, o, external_relocs, internal_relocs, keep_memory) /* Cache the results for next time, if we can. */ if (keep_memory) elf_section_data (o)->relocs = internal_relocs; - + if (alloc1 != NULL) free (alloc1); @@ -1287,11 +1338,12 @@ NAME(bfd_elf,record_link_assignment) (output_bfd, info, name, provide) based on the number of symbols there are. If there are fewer than 3 symbols we use 1 bucket, fewer than 17 symbols we use 3 buckets, fewer than 37 we use 17 buckets, and so forth. We never use more - than 521 buckets. */ + than 32771 buckets. */ static const size_t elf_buckets[] = { - 1, 3, 17, 37, 67, 97, 131, 197, 263, 521, 0 + 1, 3, 17, 37, 67, 97, 131, 197, 263, 521, 1031, 2053, 4099, 8209, + 16411, 32771, 0 }; /* Set up the sizes and contents of the ELF dynamic sections. This is @@ -1301,11 +1353,14 @@ static const size_t elf_buckets[] = boolean NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, - export_dynamic, info, sinterpptr) + export_dynamic, filter_shlib, + auxiliary_filters, info, sinterpptr) bfd *output_bfd; const char *soname; const char *rpath; boolean export_dynamic; + const char *filter_shlib; + const char * const *auxiliary_filters; struct bfd_link_info *info; asection **sinterpptr; { @@ -1317,6 +1372,13 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, if (info->hash->creator->flavour != bfd_target_elf_flavour) return true; + /* The backend may have to create some sections regardless of whether + we're dynamic or not. */ + bed = get_elf_backend_data (output_bfd); + if (bed->elf_backend_always_size_sections + && ! (*bed->elf_backend_always_size_sections) (output_bfd, info)) + return false; + dynobj = elf_hash_table (info)->dynobj; /* If there were no dynamic objects in the link, there is nothing to @@ -1356,7 +1418,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, if (indx == (bfd_size_type) -1 || ! elf_add_dynamic_entry (info, DT_SONAME, indx)) return false; - } + } if (info->symbolic) { @@ -1375,6 +1437,33 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, return false; } + if (filter_shlib != NULL) + { + bfd_size_type indx; + + indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, + filter_shlib, true, true); + if (indx == (bfd_size_type) -1 + || ! elf_add_dynamic_entry (info, DT_FILTER, indx)) + return false; + } + + if (auxiliary_filters != NULL) + { + const char * const *p; + + for (p = auxiliary_filters; *p != NULL; p++) + { + bfd_size_type indx; + + indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, + *p, true, true); + if (indx == (bfd_size_type) -1 + || ! elf_add_dynamic_entry (info, DT_AUXILIARY, indx)) + return false; + } + } + /* Find all symbols which were defined in a dynamic object and make the backend pick a reasonable value for them. */ eif.failed = false; @@ -1418,7 +1507,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, /* The backend must work out the sizes of all the other dynamic sections. */ - bed = get_elf_backend_data (output_bfd); if (! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info)) return false; @@ -1554,6 +1642,18 @@ elf_adjust_dynamic_symbol (h, data) } } + /* If this is a final link, and the symbol was defined as a common + symbol in a regular object file, and there was no definition in + any dynamic object, then the linker will have allocated space for + the symbol in a common section but the ELF_LINK_HASH_DEF_REGULAR + flag will not have been set. */ + if (h->root.type == bfd_link_hash_defined + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0 + && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) != 0 + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0 + && (h->root.u.def.section->owner->flags & DYNAMIC) == 0) + h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; + /* If -Bsymbolic was used (which means to bind references to global symbols to the definition within the shared object), and this symbol was defined in a regular object, then it actually doesn't @@ -1717,7 +1817,7 @@ struct elf_finfo_failed { boolean failed; struct elf_final_link_info *finfo; -}; +}; /* Do the final step of an ELF link. */ @@ -1798,6 +1898,12 @@ elf_bfd_final_link (abfd, info) sec = p->u.indirect.section; + /* Mark all sections which are to be included in the + link. This will normally be every section. We need + to do this so that we can identify any sections which + the linker has decided to not include. */ + sec->linker_mark = true; + if (info->relocateable) o->reloc_count += sec->reloc_count; @@ -1849,7 +1955,8 @@ elf_bfd_final_link (abfd, info) zero. This is done in elf_fake_sections as well, but forcing the VMA to 0 here will ensure that relocs against these sections are handled correctly. */ - if ((o->flags & SEC_ALLOC) == 0) + if ((o->flags & SEC_ALLOC) == 0 + && ! o->user_set_vma) o->vma = 0; } @@ -2126,7 +2233,7 @@ elf_bfd_final_link (abfd, info) { if (*rel_hash == NULL) continue; - + BFD_ASSERT ((*rel_hash)->indx >= 0); if (rel_hdr->sh_entsize == sizeof (Elf_External_Rel)) @@ -2280,11 +2387,10 @@ elf_bfd_final_link (abfd, info) if ((o->flags & SEC_HAS_CONTENTS) == 0 || o->_raw_size == 0) continue; - if ((o->flags & SEC_IN_MEMORY) == 0) + if ((o->flags & SEC_LINKER_CREATED) == 0) { /* At this point, we are only interested in sections - created by elf_link_create_dynamic_sections. FIXME: - This test is fragile. */ + created by elf_link_create_dynamic_sections. */ continue; } if ((elf_section_data (o->output_section)->this_hdr.sh_type @@ -2311,6 +2417,13 @@ elf_bfd_final_link (abfd, info) } } + /* If we have optimized stabs strings, output them. */ + if (elf_hash_table (info)->stab_info != NULL) + { + if (! _bfd_write_stab_strings (abfd, &elf_hash_table (info)->stab_info)) + goto error_return; + } + if (finfo.symstrtab != NULL) _bfd_stringtab_free (finfo.symstrtab); if (finfo.contents != NULL) @@ -2509,7 +2622,7 @@ elf_link_output_extsym (h, data) sym.st_value = 0; sym.st_size = h->size; - sym.st_other = 0; + sym.st_other = h->other; if (h->root.type == bfd_link_hash_undefweak || h->root.type == bfd_link_hash_defweak) sym.st_info = ELF_ST_INFO (STB_WEAK, h->type); @@ -2660,6 +2773,7 @@ elf_link_input_bfd (finfo, input_bfd) Elf_Internal_Shdr *symtab_hdr; size_t locsymcount; size_t extsymoff; + Elf_External_Sym *external_syms; Elf_External_Sym *esym; Elf_External_Sym *esymend; Elf_Internal_Sym *isym; @@ -2690,16 +2804,23 @@ elf_link_input_bfd (finfo, input_bfd) } /* Read the local symbols. */ - if (locsymcount > 0 - && (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || (bfd_read (finfo->external_syms, sizeof (Elf_External_Sym), + if (symtab_hdr->contents != NULL) + external_syms = (Elf_External_Sym *) symtab_hdr->contents; + else if (locsymcount == 0) + external_syms = NULL; + else + { + external_syms = finfo->external_syms; + if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 + || (bfd_read (external_syms, sizeof (Elf_External_Sym), locsymcount, input_bfd) - != locsymcount * sizeof (Elf_External_Sym)))) - return false; + != locsymcount * sizeof (Elf_External_Sym))) + return false; + } /* Swap in the local symbols and write out the ones which we know are going into the output file. */ - esym = finfo->external_syms; + esym = external_syms; esymend = esym + locsymcount; isym = finfo->internal_syms; pindex = finfo->indices; @@ -2739,7 +2860,7 @@ elf_link_input_bfd (finfo, input_bfd) *ppsection = isec; /* Don't output the first, undefined, symbol. */ - if (esym == finfo->external_syms) + if (esym == external_syms) continue; /* If we are stripping all symbols, we don't want to output this @@ -2760,9 +2881,20 @@ elf_link_input_bfd (finfo, input_bfd) if (finfo->info->discard == discard_all) continue; + /* If this symbol is defined in a section which we are + discarding, we don't need to keep it. For the benefit of the + MIPS ELF linker, we check SEC_EXCLUDE as well as linker_mark. */ + if (isym->st_shndx > 0 + && isym->st_shndx < SHN_LORESERVE + && isec != NULL + && (! isec->linker_mark + || (! finfo->info->relocateable + && (isec->flags & SEC_EXCLUDE) != 0))) + continue; + /* Get the name of the symbol. */ name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, - isym->st_name); + isym->st_name); if (name == NULL) return false; @@ -2805,31 +2937,47 @@ elf_link_input_bfd (finfo, input_bfd) /* Relocate the contents of each section. */ for (o = input_bfd->sections; o != NULL; o = o->next) { - if ((o->flags & SEC_HAS_CONTENTS) == 0) + bfd_byte *contents; + + if (! o->linker_mark) + { + /* This section was omitted from the link. */ + continue; + } + + if ((o->flags & SEC_HAS_CONTENTS) == 0 + || (o->_raw_size == 0 && (o->flags & SEC_RELOC) == 0)) continue; - if ((o->flags & SEC_IN_MEMORY) != 0 - && input_bfd == elf_hash_table (finfo->info)->dynobj) + if ((o->flags & SEC_LINKER_CREATED) != 0) { - /* Section was created by elf_link_create_dynamic_sections. - FIXME: This test is fragile. */ + /* Section was created by elf_link_create_dynamic_sections + or somesuch. */ continue; } - /* Read the contents of the section. */ - if (! bfd_get_section_contents (input_bfd, o, finfo->contents, - (file_ptr) 0, o->_raw_size)) - return false; + /* Get the contents of the section. They have been cached by a + relaxation routine. Note that o is a section in an input + file, so the contents field will not have been set by any of + the routines which work on output files. */ + if (elf_section_data (o)->this_hdr.contents != NULL) + contents = elf_section_data (o)->this_hdr.contents; + else + { + contents = finfo->contents; + if (! bfd_get_section_contents (input_bfd, o, contents, + (file_ptr) 0, o->_raw_size)) + return false; + } if ((o->flags & SEC_RELOC) != 0) { Elf_Internal_Rela *internal_relocs; /* Get the swapped relocs. */ - internal_relocs = elf_link_read_relocs (input_bfd, o, - finfo->external_relocs, - finfo->internal_relocs, - false); + internal_relocs = (NAME(_bfd_elf,link_read_relocs) + (input_bfd, o, finfo->external_relocs, + finfo->internal_relocs, false)); if (internal_relocs == NULL && o->reloc_count > 0) return false; @@ -2855,8 +3003,7 @@ elf_link_input_bfd (finfo, input_bfd) the addend to be adjusted. */ if (! (*relocate_section) (output_bfd, finfo->info, - input_bfd, o, - finfo->contents, + input_bfd, o, contents, internal_relocs, finfo->internal_syms, finfo->sections)) @@ -3026,12 +3173,22 @@ elf_link_input_bfd (finfo, input_bfd) } /* Write out the modified section contents. */ - if (! bfd_set_section_contents (output_bfd, o->output_section, - finfo->contents, o->output_offset, - (o->_cooked_size != 0 - ? o->_cooked_size - : o->_raw_size))) - return false; + if (elf_section_data (o)->stab_info == NULL) + { + if (! bfd_set_section_contents (output_bfd, o->output_section, + contents, o->output_offset, + (o->_cooked_size != 0 + ? o->_cooked_size + : o->_raw_size))) + return false; + } + else + { + if (! _bfd_write_section_stabs (output_bfd, o, + &elf_section_data (o)->stab_info, + contents)) + return false; + } } return true; @@ -3289,15 +3446,25 @@ elf_create_pointer_linker_section (abfd, info, lsect, h, rel) linker_section_ptr->written_address_p = false; *ptr_linker_section_ptr = linker_section_ptr; +#if 0 if (lsect->hole_size && lsect->hole_offset < lsect->max_hole_offset) { - linker_section_ptr->offset = lsect->section->_raw_size - lsect->hole_size; + linker_section_ptr->offset = lsect->section->_raw_size - lsect->hole_size + (ARCH_SIZE / 8); lsect->hole_offset += ARCH_SIZE / 8; lsect->sym_offset += ARCH_SIZE / 8; if (lsect->sym_hash) /* Bump up symbol value if needed */ - lsect->sym_hash->root.u.def.value += ARCH_SIZE / 8; + { + lsect->sym_hash->root.u.def.value += ARCH_SIZE / 8; +#ifdef DEBUG + fprintf (stderr, "Bump up %s by %ld, current value = %ld\n", + lsect->sym_hash->root.root.string, + (long)ARCH_SIZE / 8, + (long)lsect->sym_hash->root.u.def.value); +#endif + } } else +#endif linker_section_ptr->offset = lsect->section->_raw_size; lsect->section->_raw_size += ARCH_SIZE / 8;