X-Git-Url: https://repo.jachan.dev/binutils.git/blobdiff_plain/be1627d3092bc6a612445d5bb53416371405e8df..29f33467f23eaff819c4321f8cf9eb7fc1ac3b74:/ld/ldmain.c diff --git a/ld/ldmain.c b/ld/ldmain.c index 965aa721e9..137368bfcf 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -54,6 +54,9 @@ bfd *output_bfd = 0; extern boolean option_v; +/* set if -y on the command line */ +int had_y; + /* The local symbol prefix */ char lprefix = 'L'; @@ -184,13 +187,16 @@ main (argc, argv) ldemul_before_parse (); lang_has_input_file = false; parse_args (argc, argv); + + if (config.relocateable_output && command_line.relax) + { + einfo ("%P%F: -relax and -r may not be used together\n"); + } lang_final (); if (trace_files) { - info ("%P: mode %s\n", emulation); - } if (lang_has_input_file == false) { @@ -236,43 +242,34 @@ main (argc, argv) } if (config.relocateable_output) - { - output_bfd->flags &= ~EXEC_P; - - ldwrite (); - bfd_close (output_bfd); - } - + output_bfd->flags &= ~EXEC_P; else - { - - output_bfd->flags |= EXEC_P; - - ldwrite (); - - - if (config.make_executable == false && force_make_executable == false) - { + output_bfd->flags |= EXEC_P; - if (trace_files == true) - { - einfo ("%P: Link errors found, deleting executable `%s'\n", - output_filename); - } + ldwrite (); - if (output_bfd->iostream) - fclose ((FILE *) (output_bfd->iostream)); + /* Even if we're producing relocateable output, some non-fatal errors should + be reported in the exit status. (What non-fatal errors, if any, do we + want to ignore for relocateable output?) */ - unlink (output_filename); - exit (1); - } - else + if (config.make_executable == false && force_make_executable == false) + { + if (trace_files == true) { - bfd_close (output_bfd); + einfo ("%P: Link errors found, deleting executable `%s'\n", + output_filename); } - } + if (output_bfd->iostream) + fclose ((FILE *) (output_bfd->iostream)); + unlink (output_filename); + exit (1); + } + else + { + bfd_close (output_bfd); + } exit (0); } /* main() */ @@ -348,9 +345,11 @@ DEFUN (Q_enter_global_ref, (nlist_p, name), flagword this_symbol_flags = sym->flags; sp = ldsym_get (name); - /* If this symbol already has udata, it means that something strange + + + /* If this symbol already has udata, it means that something strange has happened. - + The strange thing is that we've had an undefined symbol resolved by an alias, but the thing the alias defined wasn't in the file. So the symbol got a udata entry, but the file wasn't loaded. Then @@ -359,128 +358,130 @@ DEFUN (Q_enter_global_ref, (nlist_p, name), if (sym->udata) - return; + return; if (flag_is_constructor (this_symbol_flags)) - { - /* Add this constructor to the list we keep */ - ldlang_add_constructor (sp); - /* Turn any commons into refs */ - if (sp->scoms_chain != (asymbol **) NULL) { - refize (sp, sp->scoms_chain); - sp->scoms_chain = 0; - } + /* Add this constructor to the list we keep */ + ldlang_add_constructor (sp); + /* Turn any commons into refs */ + if (sp->scoms_chain != (asymbol **) NULL) + { + refize (sp, sp->scoms_chain); + sp->scoms_chain = 0; + } - } + } else - { - if (sym->section == &bfd_com_section) { - /* If we have a definition of this symbol already then + if (bfd_is_com_section (sym->section)) + { + /* If we have a definition of this symbol already then this common turns into a reference. Also we only ever point to the largest common, so if we have a common, but it's bigger that the new symbol the turn this into a reference too. */ - if (sp->sdefs_chain) - { - /* This is a common symbol, but we already have a definition + if (sp->sdefs_chain) + { + /* This is a common symbol, but we already have a definition for it, so just link it into the ref chain as if it were a reference */ - refize (sp, nlist_p); - } - else if (sp->scoms_chain) - { - /* If we have a previous common, keep only the biggest */ - if ((*(sp->scoms_chain))->value > sym->value) - { - /* other common is bigger, throw this one away */ - refize (sp, nlist_p); - } - else if (sp->scoms_chain != nlist_p) - { - /* other common is smaller, throw that away */ - refize (sp, sp->scoms_chain); - sp->scoms_chain = nlist_p; - } - } - else - { - /* This is the first time we've seen a common, so remember it + refize (sp, nlist_p); + } + else if (sp->scoms_chain) + { + /* If we have a previous common, keep only the biggest */ + if ((*(sp->scoms_chain))->value > sym->value) + { + /* other common is bigger, throw this one away */ + refize (sp, nlist_p); + } + else if (sp->scoms_chain != nlist_p) + { + /* other common is smaller, throw that away */ + refize (sp, sp->scoms_chain); + sp->scoms_chain = nlist_p; + } + } + else + { + /* This is the first time we've seen a common, so remember it - if it was undefined before, we know it's defined now. If the symbol has been marked as really being a constructor, then treat this as a ref */ - if (sp->flags & SYM_CONSTRUCTOR) - { - /* Turn this into a ref */ - refize (sp, nlist_p); - } - else - { - /* treat like a common */ - if (sp->srefs_chain) - undefined_global_sym_count--; + if (sp->flags & SYM_CONSTRUCTOR) + { + /* Turn this into a ref */ + refize (sp, nlist_p); + } + else + { + /* treat like a common */ + if (sp->srefs_chain) + undefined_global_sym_count--; - commons_pending++; - sp->scoms_chain = nlist_p; + commons_pending++; + sp->scoms_chain = nlist_p; + } + } } - } - } - else if (sym->section != &bfd_und_section) - { - /* This is the definition of a symbol, add to def chain */ - if (sp->sdefs_chain && (*(sp->sdefs_chain))->section != sym->section) - { - /* Multiple definition */ - asymbol *sy = *(sp->sdefs_chain); - lang_input_statement_type *stat = (lang_input_statement_type *) sy->the_bfd->usrdata; - lang_input_statement_type *stat1 = (lang_input_statement_type *) sym->the_bfd->usrdata; - asymbol **stat1_symbols = stat1 ? stat1->asymbols : 0; - asymbol **stat_symbols = stat ? stat->asymbols : 0; - - multiple_def_count++; - einfo ("%X%C: multiple definition of `%T'\n", - sym->the_bfd, sym->section, stat1_symbols, sym->value, sym); - - einfo ("%X%C: first seen here\n", - sy->the_bfd, sy->section, stat_symbols, sy->value); - } + else if (sym->section != &bfd_und_section) + { + /* This is the definition of a symbol, add to def chain */ + if (sp->sdefs_chain && (*(sp->sdefs_chain))->section != sym->section) + { + /* Multiple definition */ + asymbol *sy = *(sp->sdefs_chain); + lang_input_statement_type *stat = + (lang_input_statement_type *) bfd_asymbol_bfd (sy)->usrdata; + lang_input_statement_type *stat1 = + (lang_input_statement_type *) bfd_asymbol_bfd (sym)->usrdata; + asymbol **stat1_symbols = stat1 ? stat1->asymbols : 0; + asymbol **stat_symbols = stat ? stat->asymbols : 0; + + multiple_def_count++; + einfo ("%X%C: multiple definition of `%T'\n", + bfd_asymbol_bfd (sym), sym->section, stat1_symbols, sym->value, sym); + + einfo ("%X%C: first seen here\n", + bfd_asymbol_bfd (sy), sy->section, stat_symbols, sy->value); + } + else + { + sym->udata = (PTR) (sp->sdefs_chain); + sp->sdefs_chain = nlist_p; + } + /* A definition overrides a common symbol */ + if (sp->scoms_chain) + { + refize (sp, sp->scoms_chain); + sp->scoms_chain = 0; + commons_pending--; + } + else if (sp->srefs_chain && relaxing == false) + { + /* If previously was undefined, then remember as defined */ + undefined_global_sym_count--; + } + } else - { - sym->udata = (PTR) (sp->sdefs_chain); - sp->sdefs_chain = nlist_p; - } - /* A definition overrides a common symbol */ - if (sp->scoms_chain) - { - refize (sp, sp->scoms_chain); - sp->scoms_chain = 0; - commons_pending--; - } - else if (sp->srefs_chain && relaxing == false) - { - /* If previously was undefined, then remember as defined */ - undefined_global_sym_count--; - } - } - else - { - if (sp->scoms_chain == (asymbol **) NULL - && sp->srefs_chain == (asymbol **) NULL - && sp->sdefs_chain == (asymbol **) NULL) - { - /* And it's the first time we've seen it */ - undefined_global_sym_count++; + { + if (sp->scoms_chain == (asymbol **) NULL + && sp->srefs_chain == (asymbol **) NULL + && sp->sdefs_chain == (asymbol **) NULL) + { + /* And it's the first time we've seen it */ + undefined_global_sym_count++; - } + } - refize (sp, nlist_p); + refize (sp, nlist_p); + } } - } ASSERT (sp->sdefs_chain == 0 || sp->scoms_chain == 0); ASSERT (sp->scoms_chain == 0 || (*(sp->scoms_chain))->udata == 0); @@ -496,7 +497,7 @@ Q_enter_file_symbols (entry) entry->common_section = bfd_make_section_old_way (entry->the_bfd, "COMMON"); - + entry->common_section->flags = SEC_NEVER_LOAD; ldlang_add_file (entry); @@ -513,7 +514,20 @@ Q_enter_file_symbols (entry) { asymbol *p = *q; - if (p->flags & BSF_INDIRECT) + if (had_y && p->name) + { + /* look up the symbol anyway to see if the trace bit was + set */ + ldsym_type *s = ldsym_get (p->name); + if (s->flags & SYM_Y) + { + einfo ("%B: %s %T\n", entry->the_bfd, + p->section == &bfd_und_section ? "reference to" : "definition of ", + p); + } + } + + if (p->section == &bfd_ind_section) { add_indirect (q); } @@ -523,7 +537,7 @@ Q_enter_file_symbols (entry) } else if (p->section == &bfd_und_section || (p->flags & BSF_GLOBAL) - || p->section == &bfd_com_section + || bfd_is_com_section (p->section) || (p->flags & BSF_CONSTRUCTOR)) { @@ -540,17 +554,19 @@ Q_enter_file_symbols (entry) } else if (p->section == &bfd_und_section || (p->flags & BSF_GLOBAL) - || p->section == &bfd_com_section + || bfd_is_com_section (p->section) || (p->flags & BSF_CONSTRUCTOR)) { Q_enter_global_ref (q, p->name); } } + } } } + /* Searching libraries */ struct lang_input_statement_struct *decode_library_subfile (); @@ -579,7 +595,7 @@ search_library (entry) #ifdef GNU960 static - boolean + boolean gnu960_check_format (abfd, format) bfd *abfd; bfd_format format; @@ -658,21 +674,37 @@ decode_library_subfile (library_entry, subfile_offset) bfd *subfile_offset; { register struct lang_input_statement_struct *subentry; - subentry = (struct lang_input_statement_struct *) ldmalloc ((bfd_size_type) (sizeof (struct lang_input_statement_struct))); - subentry->filename = subfile_offset->filename; - subentry->local_sym_name = subfile_offset->filename; - subentry->asymbols = 0; - subentry->the_bfd = subfile_offset; - subentry->subfiles = 0; - subentry->next = 0; - subentry->superfile = library_entry; - subentry->is_archive = false; - subentry->just_syms_flag = false; - subentry->loaded = false; - subentry->chain = 0; + /* First, check if we already have a loaded + lang_input_statement_struct for this library subfile. If so, + just return it. Otherwise, allocate some space and build a new one. */ + if (subfile_offset->usrdata + && ((struct lang_input_statement_struct *) subfile_offset->usrdata)-> + loaded == true) + { + subentry = (struct lang_input_statement_struct *) subfile_offset->usrdata; + } + else + { + subentry = + (struct lang_input_statement_struct *) + ldmalloc ((bfd_size_type) (sizeof (struct lang_input_statement_struct))); + + subentry->filename = subfile_offset->filename; + subentry->local_sym_name = subfile_offset->filename; + subentry->asymbols = 0; + subentry->the_bfd = subfile_offset; + subentry->subfiles = 0; + subentry->next = 0; + subentry->superfile = library_entry; + subentry->is_archive = false; + + subentry->just_syms_flag = false; + subentry->loaded = false; + subentry->chain = 0; + } return subentry; } @@ -824,9 +856,15 @@ linear_library (entry) if (entry->complained == false) { - einfo ("%P: library %s has bad table of contents, rerun ranlib\n", - entry->the_bfd->filename); + if (entry->the_bfd->xvec->flavour != bfd_target_ieee_flavour) + + { + /* IEEE can use table of contents, so this message is bogus */ + einfo ("%P: library %s has bad table of contents, rerun ranlib\n", + entry->the_bfd->filename); + } entry->complained = true; + } while (more_to_do) { @@ -836,36 +874,43 @@ linear_library (entry) more_to_do = false; while (archive) { + /* Don't check this file if it's already been read in + once */ + + if (!archive->usrdata || + !((lang_input_statement_type *) (archive->usrdata))->loaded) + { #ifdef GNU960 - if (gnu960_check_format (archive, bfd_object)) + if (gnu960_check_format (archive, bfd_object)) #else - if (bfd_check_format (archive, bfd_object)) + if (bfd_check_format (archive, bfd_object)) #endif - { - register struct lang_input_statement_struct *subentry; - - subentry = decode_library_subfile (entry, - archive); - - archive->usrdata = (PTR) subentry; - if (!subentry) - return; - if (subentry->loaded == false) { - Q_read_entry_symbols (archive, subentry); + register struct lang_input_statement_struct *subentry; + + subentry = decode_library_subfile (entry, + archive); - if (subfile_wanted_p (subentry) == true) + archive->usrdata = (PTR) subentry; + if (!subentry) + return; + if (subentry->loaded == false) { - Q_enter_file_symbols (subentry); + Q_read_entry_symbols (archive, subentry); - if (prev) - prev->chain = subentry; - else - entry->subfiles = subentry; - prev = subentry; + if (subfile_wanted_p (subentry) == true) + { + Q_enter_file_symbols (subentry); - more_to_do = true; - subentry->loaded = true; + if (prev) + prev->chain = subentry; + else + entry->subfiles = subentry; + prev = subentry; + + more_to_do = true; + subentry->loaded = true; + } } } } @@ -876,7 +921,7 @@ linear_library (entry) } } - /* ENTRY is an entry for a file inside an archive +/* ENTRY is an entry for a file inside an archive Its symbols have been read into core, but not entered into the linker ymbol table Return nonzero if we ought to load this file */ @@ -896,10 +941,10 @@ subfile_wanted_p (entry) if (p->flags & BSF_INDIRECT) { -/** add_indirect(q);*/ + /** add_indirect(q);*/ } - if (p->section == &bfd_com_section + if (bfd_is_com_section (p->section) || (p->flags & BSF_GLOBAL) || (p->flags & BSF_INDIRECT)) { @@ -913,10 +958,16 @@ subfile_wanted_p (entry) if (sp->srefs_chain != (asymbol **) NULL || sp->scoms_chain != (asymbol **) NULL) { - /* This is a symbol we are looking for. It is either - not yet defined or common. */ - - if (p->section == &bfd_com_section) + /* This is a symbol we are looking for. It is + either not yet defined or common. If this is a + common symbol, then if the symbol in the object + file is common, we need to combine sizes. But if + we already have a common symbol, and the symbol + in the object file is not common, we don't want + the object file: it is providing a definition for + a symbol that we already have a definition for + (this is the else condition below). */ + if (bfd_is_com_section (p->section)) { /* If the symbol in the table is a constructor, we won't to @@ -949,8 +1000,7 @@ subfile_wanted_p (entry) (asymbol **) ((*(sp->srefs_chain))->udata); (*(sp->scoms_chain))->udata = (PTR) NULL; - (*(sp->scoms_chain))->section = - &bfd_com_section; + (*(sp->scoms_chain))->section = p->section; (*(sp->scoms_chain))->flags = 0; /* Remember the size of this item */ sp->scoms_chain[0]->value = p->value; @@ -961,19 +1011,18 @@ subfile_wanted_p (entry) asymbol *com = *(sp->scoms_chain); if (((lang_input_statement_type *) - (com->the_bfd->usrdata))->common_section == + (bfd_asymbol_bfd (com)->usrdata))->common_section == (asection *) NULL) { ((lang_input_statement_type *) - (com->the_bfd->usrdata))->common_section = - bfd_make_section_old_way (com->the_bfd, "COMMON"); + (bfd_asymbol_bfd (com)->usrdata))->common_section = + bfd_make_section_old_way (bfd_asymbol_bfd (com), "COMMON"); } } } ASSERT (p->udata == 0); } - - else + else if (sp->scoms_chain == (asymbol **) NULL) { if (write_map) { @@ -988,3 +1037,12 @@ subfile_wanted_p (entry) return false; } + +void +add_ysym (text) + char *text; +{ + ldsym_type *lookup = ldsym_get (text); + lookup->flags |= SYM_Y; + had_y = 1; +}