diff options
Diffstat (limited to 'ld/ldmain.c')
-rw-r--r-- | ld/ldmain.c | 241 |
1 files changed, 127 insertions, 114 deletions
diff --git a/ld/ldmain.c b/ld/ldmain.c index 4258b52..f3770c0 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -70,14 +70,12 @@ int multiple_def_count; decremented when the common declaration is overridden Another way of thinking of it is that this is a count of - all ldsym_types with a ->scoms field -*/ -unsigned int commons_pending; + all ldsym_types with a ->scoms field */ +unsigned int commons_pending; /* Count the number of global symbols referenced and not defined. - common symbols are not included in this count. - */ + common symbols are not included in this count. */ unsigned int undefined_global_sym_count; @@ -89,8 +87,6 @@ int warning_count; /* have we had a load script ? */ extern boolean had_script; - - /* Nonzero means print names of input files as processed. */ boolean trace_files; @@ -106,22 +102,13 @@ int unix_relocate; enum target_flavour_enum output_flavor = BFD_BOUT_FORMAT; #endif - - - - - - - /* Force the make_executable to be output, even if there are non-fatal errors */ boolean force_make_executable; - /* A count of the total number of local symbols ever seen - by adding the symbol_count field of each newly read afile.*/ - unsigned int total_symbols_seen; /* A count of the number of read files - the same as the number of elements @@ -129,7 +116,6 @@ unsigned int total_symbols_seen; */ unsigned int total_files_seen; - /* IMPORTS */ args_type command_line; ld_config_type config; @@ -142,6 +128,7 @@ main (argc, argv) program_name = argv[0]; output_filename = "a.out"; + bfd_init(); #ifdef GNU960 { int i; @@ -163,8 +150,6 @@ main (argc, argv) /* Initialize the data about options. */ trace_files = false; - - write_map = false; config.relocateable_output = false; unix_relocate = 0; @@ -188,12 +173,8 @@ main (argc, argv) emulation= DEFAULT_EMULATION; } - ldemul_choose_mode(emulation); - - default_target = ldemul_choose_target(); - lang_init(); ldemul_before_parse(); lang_has_input_file = false; @@ -207,12 +188,8 @@ main (argc, argv) } ldemul_after_parse(); - lang_process(); - - - /* Print error messages for any missing symbols, for any warning symbols, and possibly multiple definitions */ @@ -223,6 +200,19 @@ main (argc, argv) lang_map(stdout); } + if (config.text_read_only) { + /* Look for a text section and mark the readonly attribute in it */ + asection *found = bfd_get_section_by_name(output_bfd, ".text"); + if (found == (asection *)NULL) { + info("%P%F: text marked read only, but no text section present"); + } + found->flags |= SEC_READONLY; + output_bfd->flags |= WP_TEXT; + } + else { + output_bfd->flags |= WP_TEXT; + } + if (config.relocateable_output) { output_bfd->flags &= ~( D_PAGED); @@ -253,7 +243,6 @@ Q_read_entry_symbols (desc, entry) if (entry->asymbols == (asymbol **)NULL) { bfd_size_type table_size = get_symtab_upper_bound(desc); entry->asymbols = (asymbol **)ldmalloc(table_size); - entry->symbol_count = bfd_canonicalize_symtab(desc, entry->asymbols) ; } } @@ -312,26 +301,30 @@ Q_enter_global_ref (nlist_p) ASSERT(sym->udata == 0); + if (flag_is_constructor(this_symbol_flags)) { - /* Just remeber the name, do it once per name by placing it as if - it were a zero sized common. The next ref */ - ldlang_add_constructor(sp); + /* 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 (flag_is_common(this_symbol_flags)) { /* 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. - */ + 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 for it, so just link it into the ref chain as if - it were a reference - */ + it were a reference */ refize(sp, nlist_p); } else if (sp->scoms_chain) { @@ -347,14 +340,23 @@ Q_enter_global_ref (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 (sp->srefs_chain) - undefined_global_sym_count--; - - commons_pending++; - sp->scoms_chain = nlist_p; + /* 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--; + + commons_pending++; + sp->scoms_chain = nlist_p; + } } } @@ -603,107 +605,107 @@ symdef_library (entry) while (not_finished == true) - { - carsym *exported_library_name; - bfd *prev_archive_member_bfd = 0; + { + carsym *exported_library_name; + bfd *prev_archive_member_bfd = 0; - int idx = bfd_get_next_mapent(entry->the_bfd, - BFD_NO_MORE_SYMBOLS, - &exported_library_name); + int idx = bfd_get_next_mapent(entry->the_bfd, + BFD_NO_MORE_SYMBOLS, + &exported_library_name); - not_finished = false; + not_finished = false; - while (idx != BFD_NO_MORE_SYMBOLS && undefined_global_sym_count) - { - - if (exported_library_name->name) + while (idx != BFD_NO_MORE_SYMBOLS && undefined_global_sym_count) { - ldsym_type *sp = ldsym_get_soft (exported_library_name->name); + if (exported_library_name->name) + { - /* If we find a symbol that appears to be needed, think carefully - about the archive member that the symbol is in. */ - /* So - if it exists, and is referenced somewhere and is - undefined or */ - if (sp && sp->srefs_chain && !sp->sdefs_chain) - { - bfd *archive_member_bfd = bfd_get_elt_at_index(entry->the_bfd, idx); - struct lang_input_statement_struct *archive_member_lang_input_statement_struct; + ldsym_type *sp = ldsym_get_soft (exported_library_name->name); + + /* If we find a symbol that appears to be needed, think carefully + about the archive member that the symbol is in. */ + /* So - if it exists, and is referenced somewhere and is + undefined or */ + if (sp && sp->srefs_chain && !sp->sdefs_chain) + { + bfd *archive_member_bfd = bfd_get_elt_at_index(entry->the_bfd, idx); + struct lang_input_statement_struct *archive_member_lang_input_statement_struct; #ifdef GNU960 - if (archive_member_bfd && gnu960_check_format(archive_member_bfd, bfd_object)) + if (archive_member_bfd && gnu960_check_format(archive_member_bfd, bfd_object)) #else - if (archive_member_bfd && bfd_check_format(archive_member_bfd, bfd_object)) + if (archive_member_bfd && bfd_check_format(archive_member_bfd, bfd_object)) #endif - { + { - /* Don't think carefully about any archive member - more than once in a given pass. */ - if (prev_archive_member_bfd != archive_member_bfd) - { + /* Don't think carefully about any archive member + more than once in a given pass. */ + if (prev_archive_member_bfd != archive_member_bfd) + { - prev_archive_member_bfd = archive_member_bfd; + prev_archive_member_bfd = archive_member_bfd; - /* Read the symbol table of the archive member. */ + /* Read the symbol table of the archive member. */ - if (archive_member_bfd->usrdata != (PTR)NULL) { + if (archive_member_bfd->usrdata != (PTR)NULL) { - archive_member_lang_input_statement_struct =(lang_input_statement_type *) archive_member_bfd->usrdata; - } - else { + archive_member_lang_input_statement_struct =(lang_input_statement_type *) archive_member_bfd->usrdata; + } + else { - archive_member_lang_input_statement_struct = - decode_library_subfile (entry, archive_member_bfd); - archive_member_bfd->usrdata = (PTR) archive_member_lang_input_statement_struct; + archive_member_lang_input_statement_struct = + decode_library_subfile (entry, archive_member_bfd); + archive_member_bfd->usrdata = (PTR) archive_member_lang_input_statement_struct; - } + } - if (archive_member_lang_input_statement_struct == 0) { - info ("%F%I contains invalid archive member %s\n", - entry, - sp->name); - } + if (archive_member_lang_input_statement_struct == 0) { + info ("%F%I contains invalid archive member %s\n", + entry, + sp->name); + } - if (archive_member_lang_input_statement_struct->loaded == false) - { + if (archive_member_lang_input_statement_struct->loaded == false) + { - Q_read_entry_symbols (archive_member_bfd, archive_member_lang_input_statement_struct); - /* Now scan the symbol table and decide whether to load. */ + Q_read_entry_symbols (archive_member_bfd, archive_member_lang_input_statement_struct); + /* Now scan the symbol table and decide whether to load. */ - if (subfile_wanted_p (archive_member_lang_input_statement_struct) == true) + if (subfile_wanted_p (archive_member_lang_input_statement_struct) == true) - { - /* This member is needed; load it. - Since we are loading something on this pass, - we must make another pass through the symdef data. */ + { + /* This member is needed; load it. + Since we are loading something on this pass, + we must make another pass through the symdef data. */ - not_finished = true; + not_finished = true; - Q_enter_file_symbols (archive_member_lang_input_statement_struct); + Q_enter_file_symbols (archive_member_lang_input_statement_struct); - if (prev) - prev->chain = archive_member_lang_input_statement_struct; - else - entry->subfiles = archive_member_lang_input_statement_struct; + if (prev) + prev->chain = archive_member_lang_input_statement_struct; + else + entry->subfiles = archive_member_lang_input_statement_struct; - prev = archive_member_lang_input_statement_struct; + prev = archive_member_lang_input_statement_struct; - /* Clear out this member's symbols from the symdef data - so that following passes won't waste time on them. */ - clear_syms(entry, exported_library_name->file_offset); - archive_member_lang_input_statement_struct->loaded = true; + /* Clear out this member's symbols from the symdef data + so that following passes won't waste time on them. */ + clear_syms(entry, exported_library_name->file_offset); + archive_member_lang_input_statement_struct->loaded = true; + } + } + } } - } } - } - } + } + idx = bfd_get_next_mapent(entry->the_bfd, idx, &exported_library_name); } - idx = bfd_get_next_mapent(entry->the_bfd, idx, &exported_library_name); - } - } + } } void @@ -774,6 +776,12 @@ struct lang_input_statement_struct *entry; /* If the symbol has an interesting definition, we could potentially want it. */ + if (p->flags & BSF_INDIRECT) { + /* Grab out the name we've indirected to, and keep the insides + */ + add_indirect(q); + } + if (p->flags & BSF_FORT_COMM || p->flags & BSF_GLOBAL) { @@ -792,6 +800,10 @@ struct lang_input_statement_struct *entry; if (flag_is_common(p->flags)) { + + /* If the symbol in the table is a constructor, we won't to + anything fancy with it */ + if ((sp->flags & SYM_CONSTRUCTOR) == 0) { /* This libary member has something to say about this element. We should remember if its a new size */ @@ -830,6 +842,7 @@ struct lang_input_statement_struct *entry; bfd_make_section(com->the_bfd, "COMMON"); } } + } ASSERT(p->udata == 0); } |