From 8e5090ce3a68e4a0285a1a9572c75f84d573478a Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 9 May 1994 23:22:00 +0000 Subject: [PATCH] * linker.c (_bfd_generic_link_add_one_symbol): If hashp and *hashp are not NULL, assume the caller has already looked up the symbol in the hash table and has stored the entry in *hashp. (generic_link_add_symbol_list): Set h to NULL before calling _bfd_generic_link_add_one_symbol. * ecoff.c (ecoff_link_add_externals): Likewise. --- bfd/ChangeLog | 10 +++ bfd/ecoff.c | 184 +++++++++++++++++++++++------------------------- bfd/linker.c | 190 ++++++++++++++++++++++++++------------------------ 3 files changed, 195 insertions(+), 189 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index ab6ca34b74..435aff61a6 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,15 @@ Mon May 9 11:53:54 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + * linker.c (_bfd_generic_link_add_one_symbol): If hashp and *hashp + are not NULL, assume the caller has already looked up the symbol + in the hash table and has stored the entry in *hashp. + (generic_link_add_symbol_list): Set h to NULL before calling + _bfd_generic_link_add_one_symbol. + * ecoff.c (ecoff_link_add_externals): Likewise. + + * elfcode.h (assign_file_positions_except_relocs): Don't require + page shared between .data and .bss segments to contain zeroes. + * elfcode.h: Include bfdlink.h. Added several new functions to do linking. (ELF_R_TYPE): Define. diff --git a/bfd/ecoff.c b/bfd/ecoff.c index 3aa939e5cc..ce4d5f6c6f 100644 --- a/bfd/ecoff.c +++ b/bfd/ecoff.c @@ -99,7 +99,6 @@ ecoff_mkobject_hook (abfd, filehdr, aouthdr) struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr; struct internal_aouthdr *internal_a = (struct internal_aouthdr *) aouthdr; ecoff_data_type *ecoff; - asection *regsec; if (ecoff_mkobject (abfd) == false) return NULL; @@ -108,13 +107,6 @@ ecoff_mkobject_hook (abfd, filehdr, aouthdr) ecoff->gp_size = 8; ecoff->sym_filepos = internal_f->f_symptr; - /* Create the .reginfo section to give programs outside BFD a way to - see the information stored in the a.out header. See the comment - in coff/ecoff.h. */ - regsec = bfd_make_section (abfd, REGINFO); - if (regsec == NULL) - return NULL; - if (internal_a != (struct internal_aouthdr *) NULL) { int i; @@ -184,15 +176,6 @@ ecoff_new_section_hook (abfd, section) /* An Irix 4 shared libary. */ section->flags |= SEC_SHARED_LIBRARY; } - else if (strcmp (section->name, REGINFO) == 0) - { - /* Setting SEC_SHARED_LIBRARY should make the linker leave the - section completely alone. */ - section->flags |= (SEC_SHARED_LIBRARY - | SEC_HAS_CONTENTS - | SEC_NEVER_LOAD); - section->_raw_size = sizeof (struct ecoff_reginfo); - } /* Probably any other section name is SEC_NEVER_LOAD, but I'm uncertain about .init on some systems and I don't know how shared @@ -2187,12 +2170,21 @@ ecoff_bfd_copy_private_bfd_data (ibfd, obfd) { struct ecoff_debug_info *iinfo = &ecoff_data (ibfd)->debug_info; struct ecoff_debug_info *oinfo = &ecoff_data (obfd)->debug_info; + register int i; asymbol **sym_ptr_ptr; size_t c; boolean local; BFD_ASSERT (ibfd->xvec == obfd->xvec); + /* Copy the GP value and the register masks. */ + ecoff_data (obfd)->gp = ecoff_data (ibfd)->gp; + ecoff_data (obfd)->gprmask = ecoff_data (ibfd)->gprmask; + ecoff_data (obfd)->fprmask = ecoff_data (ibfd)->fprmask; + for (i = 0; i < 3; i++) + ecoff_data (obfd)->cprmask[i] = ecoff_data (ibfd)->cprmask[i]; + + /* Copy the version stamp. */ oinfo->symbolic_header.vstamp = iinfo->symbolic_header.vstamp; /* If there are no symbols, don't copy any debugging information. */ @@ -2287,8 +2279,7 @@ ecoff_set_arch_mach (abfd, arch, machine) return arch == ecoff_backend (abfd)->arch; } -/* Get the size of the section headers. We do not output the .reginfo - section. */ +/* Get the size of the section headers. */ /*ARGSUSED*/ int @@ -2304,8 +2295,7 @@ ecoff_sizeof_headers (abfd, reloc) for (current = abfd->sections; current != (asection *)NULL; current = current->next) - if (strcmp (current->name, REGINFO) != 0) - ++c; + ++c; ret = (bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd) @@ -2313,9 +2303,7 @@ ecoff_sizeof_headers (abfd, reloc) return BFD_ALIGN (ret, 16); } -/* Get the contents of a section. This is where we handle reading the - .reginfo section, which implicitly holds the contents of an - ecoff_reginfo structure. */ +/* Get the contents of a section. */ boolean ecoff_get_section_contents (abfd, section, location, offset, count) @@ -2325,26 +2313,8 @@ ecoff_get_section_contents (abfd, section, location, offset, count) file_ptr offset; bfd_size_type count; { - ecoff_data_type *tdata = ecoff_data (abfd); - struct ecoff_reginfo s; - int i; - - if (strcmp (section->name, REGINFO) != 0) - return _bfd_generic_get_section_contents (abfd, section, location, - offset, count); - - s.gp_value = tdata->gp; - s.gprmask = tdata->gprmask; - for (i = 0; i < 4; i++) - s.cprmask[i] = tdata->cprmask[i]; - s.fprmask = tdata->fprmask; - - /* bfd_get_section_contents has already checked that the offset and - size is reasonable. We don't have to worry about swapping or any - such thing; the .reginfo section is defined such that the - contents are an ecoff_reginfo structure as seen on the host. */ - memcpy (location, ((char *) &s) + offset, (size_t) count); - return true; + return _bfd_generic_get_section_contents (abfd, section, location, + offset, count); } /* Calculate the file position for each section, and set @@ -2369,8 +2339,7 @@ ecoff_compute_section_file_positions (abfd) unsigned int alignment_power; /* Only deal with sections which have contents */ - if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0 - || strcmp (current->name, REGINFO) == 0) + if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0) continue; /* For the Alpha ECOFF .pdata section the lnnoptr field is @@ -2460,8 +2429,6 @@ ecoff_compute_reloc_file_positions (abfd) current != (asection *)NULL; current = current->next) { - if (strcmp (current->name, REGINFO) == 0) - continue; if (current->reloc_count == 0) current->rel_filepos = 0; else @@ -2490,9 +2457,7 @@ ecoff_compute_reloc_file_positions (abfd) return reloc_size; } -/* Set the contents of a section. This is where we handle setting the - contents of the .reginfo section, which implicitly holds a - ecoff_reginfo structure. */ +/* Set the contents of a section. */ boolean ecoff_set_section_contents (abfd, section, location, offset, count) @@ -2516,39 +2481,6 @@ ecoff_set_section_contents (abfd, section, location, offset, count) if (count == 0) return true; - if (strcmp (section->name, REGINFO) == 0) - { - ecoff_data_type *tdata = ecoff_data (abfd); - struct ecoff_reginfo s; - int i; - - /* If the caller is only changing part of the structure, we must - retrieve the current information before the memcpy. */ - if (offset != 0 || count != sizeof (struct ecoff_reginfo)) - { - s.gp_value = tdata->gp; - s.gprmask = tdata->gprmask; - for (i = 0; i < 4; i++) - s.cprmask[i] = tdata->cprmask[i]; - s.fprmask = tdata->fprmask; - } - - /* bfd_set_section_contents has already checked that the offset - and size is reasonable. We don't have to worry about - swapping or any such thing; the .reginfo section is defined - such that the contents are an ecoff_reginfo structure as seen - on the host. */ - memcpy (((char *) &s) + offset, location, (size_t) count); - - tdata->gp = s.gp_value; - tdata->gprmask = s.gprmask; - for (i = 0; i < 4; i++) - tdata->cprmask[i] = s.cprmask[i]; - tdata->fprmask = s.fprmask; - - return true; - } - if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0 || bfd_write (location, 1, count, abfd) != count) return false; @@ -2556,6 +2488,76 @@ ecoff_set_section_contents (abfd, section, location, offset, count) return true; } +/* Get the GP value for an ECOFF file. This is a hook used by + nlmconv. */ + +bfd_vma +bfd_ecoff_get_gp_value (abfd) + bfd *abfd; +{ + if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour + || bfd_get_format (abfd) != bfd_object) + { + bfd_set_error (bfd_error_invalid_operation); + return 0; + } + + return ecoff_data (abfd)->gp; +} + +/* Set the GP value for an ECOFF file. This is a hook used by the + assembler. */ + +boolean +bfd_ecoff_set_gp_value (abfd, gp_value) + bfd *abfd; + bfd_vma gp_value; +{ + if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour + || bfd_get_format (abfd) != bfd_object) + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } + + ecoff_data (abfd)->gp = gp_value; + + return true; +} + +/* Set the register masks for an ECOFF file. This is a hook used by + the assembler. */ + +boolean +bfd_ecoff_set_regmasks (abfd, gprmask, fprmask, cprmask) + bfd *abfd; + unsigned long gprmask; + unsigned long fprmask; + unsigned long *cprmask; +{ + ecoff_data_type *tdata; + + if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour + || bfd_get_format (abfd) != bfd_object) + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } + + tdata = ecoff_data (abfd); + tdata->gprmask = gprmask; + tdata->fprmask = fprmask; + if (cprmask != (unsigned long *) NULL) + { + register int i; + + for (i = 0; i < 3; i++) + tdata->cprmask[i] = cprmask[i]; + } + + return true; +} + /* Get ECOFF EXTR information for an external symbol. This function is passed to bfd_ecoff_debug_externals. */ @@ -2681,8 +2683,6 @@ ecoff_write_object_contents (abfd) current != (asection *)NULL; current = current->next) { - if (strcmp (current->name, REGINFO) == 0) - continue; current->target_index = count; ++count; } @@ -2727,12 +2727,6 @@ ecoff_write_object_contents (abfd) struct internal_scnhdr section; bfd_vma vma; - if (strcmp (current->name, REGINFO) == 0) - { - BFD_ASSERT (current->reloc_count == 0); - continue; - } - ++internal_f.f_nscns; strncpy (section.s_name, current->name, sizeof section.s_name); @@ -4150,6 +4144,7 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext) name = ssext + esym.asym.iss; + h = NULL; if (! (_bfd_generic_link_add_one_symbol (info, abfd, name, BSF_GLOBAL, section, value, (const char *) NULL, true, true, @@ -4359,11 +4354,6 @@ ecoff_bfd_final_link (abfd, info) for (o = abfd->sections; o != (asection *) NULL; o = o->next) { - /* Ignore any link_orders for the .reginfo section, which does - not really exist. */ - if (strcmp (o->name, REGINFO) == 0) - continue; - for (p = o->link_order_head; p != (struct bfd_link_order *) NULL; p = p->next) diff --git a/bfd/linker.c b/bfd/linker.c index 276d476d54..5f11daf372 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -412,6 +412,8 @@ SUBSUBSECTION static struct bfd_hash_entry *generic_link_hash_newfunc PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); +static boolean generic_link_read_symbols + PARAMS ((bfd *)); static boolean generic_link_add_symbols PARAMS ((bfd *, struct bfd_link_info *, boolean collect)); static boolean generic_link_add_object_symbols @@ -610,6 +612,40 @@ _bfd_generic_link_hash_table_create (abfd) } return &ret->root; } + +/* Grab the symbols for an object file when doing a generic link. We + store the symbols in the outsymbols field. We need to keep them + around for the entire link to ensure that we only read them once. + If we read them multiple times, we might wind up with relocs and + the hash table pointing to different instances of the symbol + structure. */ + +static boolean +generic_link_read_symbols (abfd) + bfd *abfd; +{ + if (abfd->outsymbols == (asymbol **) NULL) + { + long symsize; + long symcount; + + symsize = bfd_get_symtab_upper_bound (abfd); + if (symsize < 0) + return false; + abfd->outsymbols = (asymbol **) bfd_alloc (abfd, symsize); + if (abfd->outsymbols == NULL && symsize != 0) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + symcount = bfd_canonicalize_symtab (abfd, abfd->outsymbols); + if (symcount < 0) + return false; + abfd->symcount = symcount; + } + + return true; +} /* Generic function to add symbols to from an object file to the global hash table. This version does not automatically collect @@ -676,24 +712,12 @@ generic_link_add_object_symbols (abfd, info, collect) struct bfd_link_info *info; boolean collect; { - size_t symsize; - asymbol **symbols; - bfd_size_type symbol_count; - boolean result; - - symsize = get_symtab_upper_bound (abfd); - symbols = (asymbol **) malloc (symsize); - if (symbols == NULL && symsize != 0) - { - bfd_set_error (bfd_error_no_memory); - return false; - } - symbol_count = bfd_canonicalize_symtab (abfd, symbols); - - result = generic_link_add_symbol_list (abfd, info, symbol_count, symbols, - collect); - free (symbols); - return result; + if (! generic_link_read_symbols (abfd)) + return false; + return generic_link_add_symbol_list (abfd, info, + _bfd_generic_link_get_symcount (abfd), + _bfd_generic_link_get_symbols (abfd), + collect); } /* We build a hash table of all symbols defined in an archive. */ @@ -1005,25 +1029,15 @@ generic_link_check_archive_element (abfd, info, pneeded, collect) boolean *pneeded; boolean collect; { - size_t symsize; - asymbol **symbols = NULL; - bfd_size_type symbol_count; asymbol **pp, **ppend; *pneeded = false; - symsize = get_symtab_upper_bound (abfd); - symbols = (asymbol **) malloc (symsize); - if (symbols == NULL && symsize != 0) - { - bfd_set_error (bfd_error_no_memory); - goto error_return; - } + if (! generic_link_read_symbols (abfd)) + return false; - symbol_count = bfd_canonicalize_symtab (abfd, symbols); - - pp = symbols; - ppend = symbols + symbol_count; + pp = _bfd_generic_link_get_symbols (abfd); + ppend = pp + _bfd_generic_link_get_symcount (abfd); for (; pp < ppend; pp++) { asymbol *p; @@ -1052,15 +1066,20 @@ generic_link_check_archive_element (abfd, info, pneeded, collect) if (! bfd_is_com_section (p->section)) { + bfd_size_type symcount; + asymbol **symbols; + /* This object file defines this symbol, so pull it in. */ if (! (*info->callbacks->add_archive_element) (info, abfd, bfd_asymbol_name (p))) - goto error_return; - if (! generic_link_add_symbol_list (abfd, info, symbol_count, + return false; + symcount = _bfd_generic_link_get_symcount (abfd); + symbols = _bfd_generic_link_get_symbols (abfd); + if (! generic_link_add_symbol_list (abfd, info, symcount, symbols, collect)) - goto error_return; + return false; *pneeded = true; - goto successful_return; + return true; } /* P is a common symbol. */ @@ -1077,9 +1096,9 @@ generic_link_check_archive_element (abfd, info, pneeded, collect) file. This is for the -u option in the linker. */ if (! (*info->callbacks->add_archive_element) (info, abfd, bfd_asymbol_name (p))) - goto error_return; + return false; *pneeded = true; - goto successful_return; + return true; } /* Turn the symbol into a common symbol but do not link in @@ -1110,16 +1129,7 @@ generic_link_check_archive_element (abfd, info, pneeded, collect) } /* This archive element is not needed. */ - - successful_return: - if (symbols != NULL) - free (symbols); return true; - - error_return: - if (symbols != NULL) - free (symbols); - return false; } /* Add the symbols from an object file to the global hash table. ABFD @@ -1174,6 +1184,7 @@ generic_link_add_symbol_list (abfd, info, symbol_count, symbols, collect) else string = NULL; + h = NULL; if (! (_bfd_generic_link_add_one_symbol (info, abfd, name, p->flags, bfd_get_section (p), p->value, string, false, collect, @@ -1202,6 +1213,11 @@ generic_link_add_symbol_list (abfd, info, symbol_count, symbols, collect) if (bfd_is_com_section (bfd_get_section (p))) p->flags |= BSF_OLD_COMMON; } + + /* Store a back pointer from the symbol to the hash + table entry for the benefit of relaxation code until + it gets rewritten to not use asymbol structures. */ + p->udata = (PTR) h; } } } @@ -1282,7 +1298,8 @@ static const enum link_action link_action[8][7] = COLLECT is true if we should automatically collect gcc constructor or destructor names as collect2 does. HASHP, if not NULL, is a place to store the created hash table - entry. */ + entry; if *HASHP is not NULL, the caller has already looked up + the hash table entry, and stored it in *HASHP. boolean _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, @@ -1323,12 +1340,20 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, else row = DEF_ROW; - h = bfd_link_hash_lookup (info->hash, name, true, copy, false); - if (h == (struct bfd_link_hash_entry *) NULL) + if (hashp != NULL && *hashp != NULL) { - if (hashp != (struct bfd_link_hash_entry **) NULL) - *hashp = NULL; - return false; + h = *hashp; + BFD_ASSERT (strcmp (h->name, name) == 0); + } + else + { + h = bfd_link_hash_lookup (info->hash, name, true, copy, false); + if (h == NULL) + { + if (hashp != NULL) + *hashp = NULL; + return false; + } } if (info->notice_hash != (struct bfd_hash_table *) NULL @@ -1576,8 +1601,7 @@ _bfd_generic_final_link (abfd, info) abfd->symcount = 0; outsymalloc = 0; - /* Build the output symbol table. This also reads in the symbols - for all the input BFDs, keeping them in the outsymbols field. */ + /* Build the output symbol table. */ for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next) if (! _bfd_generic_link_output_symbols (abfd, sub, info, &outsymalloc)) return false; @@ -1609,24 +1633,30 @@ _bfd_generic_final_link (abfd, info) { asection *input_section; bfd *input_bfd; - bfd_size_type relsize; + long relsize; arelent **relocs; - bfd_size_type reloc_count; + asymbol **symbols; + long reloc_count; input_section = p->u.indirect.section; input_bfd = input_section->owner; relsize = bfd_get_reloc_upper_bound (input_bfd, input_section); + if (relsize < 0) + return false; relocs = (arelent **) malloc ((size_t) relsize); if (!relocs && relsize != 0) { bfd_set_error (bfd_error_no_memory); return false; } - reloc_count = - bfd_canonicalize_reloc (input_bfd, input_section, - relocs, - bfd_get_outsymbols (input_bfd)); + symbols = _bfd_generic_link_get_symbols (input_bfd); + reloc_count = bfd_canonicalize_reloc (input_bfd, + input_section, + relocs, + symbols); + if (reloc_count < 0) + return false; BFD_ASSERT (reloc_count == input_section->reloc_count); o->reloc_count += reloc_count; free (relocs); @@ -1722,23 +1752,11 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc) struct bfd_link_info *info; size_t *psymalloc; { - size_t symsize; asymbol **sym_ptr; asymbol **sym_end; - /* Do not clobber outsymbols if they have already been created. */ - if (input_bfd->outsymbols == NULL) - { - symsize = get_symtab_upper_bound (input_bfd); - input_bfd->outsymbols = (asymbol **) bfd_alloc (input_bfd, symsize); - if (!input_bfd->outsymbols) - { - bfd_set_error (bfd_error_no_memory); - return false; - } - input_bfd->symcount = bfd_canonicalize_symtab (input_bfd, - input_bfd->outsymbols); - } + if (! generic_link_read_symbols (input_bfd)) + return false; /* Create a filename symbol if we are supposed to. */ if (info->create_object_symbols_section != (asection *) NULL) @@ -1772,8 +1790,8 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc) /* Adjust the values of the globally visible symbols, and write out local symbols. */ - sym_ptr = bfd_get_outsymbols (input_bfd); - sym_end = sym_ptr + bfd_get_symcount (input_bfd); + sym_ptr = _bfd_generic_link_get_symbols (input_bfd); + sym_end = sym_ptr + _bfd_generic_link_get_symcount (input_bfd); for (; sym_ptr < sym_end; sym_ptr++) { asymbol *sym; @@ -2252,20 +2270,8 @@ default_indirect_link_order (output_bfd, info, output_section, link_order) retrieved them by this point, but we may be being called by a specific linker when linking different types of object files together. */ - if (bfd_get_outsymbols (input_bfd) == (asymbol **) NULL) - { - size_t symsize; - - symsize = get_symtab_upper_bound (input_bfd); - input_bfd->outsymbols = (asymbol **) bfd_alloc (input_bfd, symsize); - if (!input_bfd->outsymbols) - { - bfd_set_error (bfd_error_no_memory); - return false; - } - input_bfd->symcount = bfd_canonicalize_symtab (input_bfd, - input_bfd->outsymbols); - } + if (! generic_link_read_symbols (input_bfd)) + return false; /* Get and relocate the section contents. */ contents = (bfd_byte *) malloc (bfd_section_size (input_bfd, input_section)); @@ -2276,7 +2282,7 @@ default_indirect_link_order (output_bfd, info, output_section, link_order) } new_contents = (bfd_get_relocated_section_contents (output_bfd, info, link_order, contents, info->relocateable, - bfd_get_outsymbols (input_bfd))); + _bfd_generic_link_get_symbols (input_bfd))); if (!new_contents) goto error_return;