diff options
-rw-r--r-- | ld/ChangeLog | 11 | ||||
-rw-r--r-- | ld/emultempl/elf32.em | 247 |
2 files changed, 236 insertions, 22 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index 8dd38b7..605d189 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,14 @@ +Tue Jul 4 12:55:48 1995 Ian Lance Taylor <ian@cygnus.com> + + * emultempl/elf32.em (global_needed): New static variable. + (global_found): Likewise. + (gld${EMULATION_NAME}_after_open): New static function. + (gld${EMULATION_NAME}_search_needed): Likewise. + (gld${EMULATION_NAME}_try_needed): Likewise. + (gld${EMULATION_NAME}_check_needed): Likewise. + (ld_${EMULATION_NAME}_emulation): Replace after_open_default with + gld${EMULATION_NAME}_after_open. + Mon Jul 3 14:26:37 1995 Steve Chamberlain <sac@slash.cygnus.com> * configure.in (i386-*-win32): New target. diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 0f4ee72..9cfb3ea 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -46,6 +46,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ static void gld${EMULATION_NAME}_before_parse PARAMS ((void)); static boolean gld${EMULATION_NAME}_open_dynamic_archive PARAMS ((const char *, lang_input_statement_type *)); +static void gld${EMULATION_NAME}_after_open PARAMS ((void)); +static void gld${EMULATION_NAME}_check_needed + PARAMS ((lang_input_statement_type *)); +static boolean gld${EMULATION_NAME}_search_needed + PARAMS ((const char *, const char *)); +static boolean gld${EMULATION_NAME}_try_needed PARAMS ((const char *)); static void gld${EMULATION_NAME}_before_allocation PARAMS ((void)); static void gld${EMULATION_NAME}_find_statement_assignment PARAMS ((lang_statement_union_type *)); @@ -107,6 +113,174 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, entry) return true; } +/* These variables are required to pass information back and forth + between after_open and check_needed. */ + +static struct bfd_elf_link_needed_list *global_needed; +static boolean global_found; + +/* This is called after all the input files have been opened. */ + +static void +gld${EMULATION_NAME}_after_open () +{ + struct bfd_elf_link_needed_list *needed, *l; + + /* Get the list of files which appear in DT_NEEDED entries in + dynamic objects included in the link (often there will be none). + For each such file, we want to track down the corresponding + library, and include the symbol table in the link. This is what + the runtime dynamic linker will do. Tracking the files down here + permits one dynamic object to include another without requiring + special action by the person doing the link. Note that the + needed list can actually grow while we are stepping through this + loop. */ + needed = bfd_elf_get_needed_list (output_bfd, &link_info); + for (l = needed; l != NULL; l = l->next) + { + struct bfd_elf_link_needed_list *ll; + const char *lib_path; + size_t len; + search_dirs_type *search; + + /* If we've already seen this file, skip it. */ + for (ll = needed; ll != l; ll = ll->next) + if (strcmp (ll->name, l->name) == 0) + break; + if (ll != l) + continue; + + /* See if this file was included in the link explicitly. */ + global_needed = l; + global_found = false; + lang_for_each_input_file (gld${EMULATION_NAME}_check_needed); + if (global_found) + continue; + + /* We need to find this file and include the symbol table. We + want to search for the file in the same way that the dynamic + linker will search. That means that we want to use rpath, + then the environment variable LD_LIBRARY_PATH, then the + linker script LIB_SEARCH_DIRS. We do not search using the -L + arguments. */ + if (gld${EMULATION_NAME}_search_needed (command_line.rpath, l->name)) + continue; + lib_path = (const char *) getenv ("LD_LIBRARY_PATH"); + if (gld${EMULATION_NAME}_search_needed (lib_path, l->name)) + continue; + len = strlen (l->name); + for (search = search_head; search != NULL; search = search->next) + { + char *filename; + + if (search->cmdline) + continue; + filename = (char *) xmalloc (strlen (search->name) + len + 2); + sprintf (filename, "%s/%s", search->name, l->name); + if (gld${EMULATION_NAME}_try_needed (filename)) + break; + free (filename); + } + if (search != NULL) + continue; + + einfo ("%P: warning: %s, needed by %B, not found\n", + l->name, l->by); + } +} + +/* Search for a needed file in a path. */ + +static boolean +gld${EMULATION_NAME}_search_needed (path, name) + const char *path; + const char *name; +{ + const char *s; + size_t len; + + if (path == NULL || *path == '\0') + return false; + len = strlen (name); + while (1) + { + char *filename, *sset; + + s = strchr (path, ':'); + if (s == NULL) + s = path + strlen (path); + + filename = (char *) xmalloc (s - path + len + 2); + if (s == path) + sset = filename; + else + { + memcpy (filename, path, s - path); + filename[s - path] = '/'; + sset = filename + (s - path) + 1; + } + strcpy (sset, name); + + if (gld${EMULATION_NAME}_try_needed (filename)) + return true; + + free (filename); + + if (*s == '\0') + break; + path = s + 1; + } + + return false; +} + +/* This function is called for each possible name for a dynamic object + named by a DT_NEEDED entry. */ + +static boolean +gld${EMULATION_NAME}_try_needed (name) + const char *name; +{ + bfd *abfd; + + abfd = bfd_openr (name, bfd_get_target (output_bfd)); + if (abfd == NULL) + return false; + if (! bfd_check_format (abfd, bfd_object)) + { + (void) bfd_close (abfd); + return false; + } + if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0) + { + (void) bfd_close (abfd); + return false; + } + + /* We've found a dynamic object matching the DT_NEEDED entry. */ + + /* Tell the ELF backend that don't want the output file to have a + DT_NEEDED entry for this file. */ + bfd_elf_set_dt_needed_name (abfd, ""); + + /* Add this file into the symbol table. */ + if (! bfd_link_add_symbols (abfd, &link_info)) + einfo ("%F%B: could not read symbols: %E\n", abfd); + + return true; +} + +/* See if an input file matches a DT_NEEDED entry. */ + +static void +gld${EMULATION_NAME}_check_needed (s) + lang_input_statement_type *s; +{ + if (s->filename != NULL + && strcmp (s->filename, global_needed->name) == 0) + global_found = true; +} + /* This is called after the sections have been attached to output sections, but before any sizes or addresses have been set. */ @@ -173,6 +347,37 @@ gld${EMULATION_NAME}_before_allocation () s->_raw_size = 0; } } + +#if defined (TARGET_IS_elf32bmip) || defined (TARGET_IS_elf32lmip) + /* For MIPS ELF the .reginfo section requires special handling. + Each input section is 24 bytes, and the final output section must + also be 24 bytes. We handle this by clobbering all but the first + input section size to 0. The .reginfo section is handled + specially by the backend code anyhow. */ + { + boolean found = false; + LANG_FOR_EACH_INPUT_STATEMENT (is) + { + asection *s; + + if (is->just_syms_flag) + continue; + + s = bfd_get_section_by_name (is->the_bfd, ".reginfo"); + if (s == NULL) + continue; + + if (! found) + { + found = true; + continue; + } + + s->_raw_size = 0; + s->_cooked_size = 0; + } + } +#endif } /* This is called by the before_allocation routine via @@ -235,6 +440,7 @@ static lang_output_section_statement_type *hold_use; static lang_output_section_statement_type *hold_text; static lang_output_section_statement_type *hold_data; static lang_output_section_statement_type *hold_bss; +static lang_output_section_statement_type *hold_rel; /*ARGSUSED*/ static boolean @@ -265,8 +471,10 @@ gld${EMULATION_NAME}_place_orphan (file, s) return true; } + secname = bfd_get_section_name (s->owner, s); + /* Decide which segment the section should go in based on the - section flags. */ + section name and section flags. */ place = NULL; if ((s->flags & SEC_HAS_CONTENTS) == 0 && hold_bss != NULL) @@ -274,37 +482,29 @@ gld${EMULATION_NAME}_place_orphan (file, s) else if ((s->flags & SEC_READONLY) == 0 && hold_data != NULL) place = hold_data; + else if (strncmp (secname, ".rel", 4) == 0 + && hold_rel != NULL) + place = hold_rel; else if ((s->flags & SEC_READONLY) != 0 && hold_text != NULL) place = hold_text; if (place == NULL) return false; - secname = bfd_get_section_name (s->owner, s); - - /* When generating an object which is to be dynamically linked, we - do not support orphaned reloc sections. This is because all the - reloc sections must be contiguous in order to generate correct - DT_REL entries. When this case arises, you can just add the - appropriate reloc sections to the linker script. Note that the - .rel.plt section must always be the last reloc section. FIXME: - This should simply be handled correctly here. */ - ASSERT (strncmp (secname, ".rel", 4) != 0 - || bfd_get_section_by_name (output_bfd, ".dynamic") == NULL); - /* Create the section in the output file, and put it in the right - place. This shuffling to make the output file look neater, and - also means that the BFD backend does not have to sort the - sections in order by address. */ + place. This shuffling is to make the output file look neater. */ snew = bfd_make_section (output_bfd, secname); if (snew == NULL) einfo ("%P%F: output format %s cannot represent section called %s\n", output_bfd->xvec->name, secname); - for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next) - ; - *pps = snew->next; - snew->next = place->bfd_section->next; - place->bfd_section->next = snew; + if (place->bfd_section != NULL) + { + for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next) + ; + *pps = snew->next; + snew->next = place->bfd_section->next; + place->bfd_section->next = snew; + } /* Start building a list of statements for this section. */ old = stat_ptr; @@ -382,6 +582,9 @@ gld${EMULATION_NAME}_place_section (s) hold_data = os; else if (strcmp (os->name, ".bss") == 0) hold_bss = os; + else if (hold_rel == NULL + && strncmp (os->name, ".rel", 4) == 0) + hold_rel = os; } static char * @@ -451,7 +654,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = syslib_default, hll_default, after_parse_default, - after_open_default, + gld${EMULATION_NAME}_after_open, after_allocation_default, set_output_arch_default, ldemul_default_target, |