diff options
author | Ian Lance Taylor <ian@airs.com> | 1994-11-12 20:54:09 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1994-11-12 20:54:09 +0000 |
commit | 5efddb2e7c3229b569a862205f61d42860af678b (patch) | |
tree | 342dc1f0c98e56bf54c2b15ef65776bb39c15c23 /ld/emultempl | |
parent | d360e1e0a19bef5bc552835e53a9f69aafcde455 (diff) | |
download | gdb-5efddb2e7c3229b569a862205f61d42860af678b.zip gdb-5efddb2e7c3229b569a862205f61d42860af678b.tar.gz gdb-5efddb2e7c3229b569a862205f61d42860af678b.tar.bz2 |
* ld.h (args_type): Add field export_dynamic.
* lexsup.c (parse_args): Recognize --export-dynamic.
* emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation):
Pass export_dynamic argument to bfd_elf32_size_dynamic_sections.
Diffstat (limited to 'ld/emultempl')
-rw-r--r-- | ld/emultempl/elf32.em | 219 |
1 files changed, 216 insertions, 3 deletions
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 7585f41..a5f6ec5 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -28,6 +28,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "bfd.h" #include "sysdep.h" + +#include <ctype.h> + #include "bfdlink.h" #include "ld.h" @@ -38,19 +41,70 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ldmisc.h" #include "ldexp.h" #include "ldlang.h" +#include "ldgram.h" 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}_before_allocation PARAMS ((void)); static void gld${EMULATION_NAME}_find_statement_assignment PARAMS ((lang_statement_union_type *)); static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *)); +static boolean gld${EMULATION_NAME}_place_orphan + PARAMS ((lang_input_statement_type *, asection *)); +static void gld${EMULATION_NAME}_place_section + PARAMS ((lang_statement_union_type *)); static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile)); static void gld${EMULATION_NAME}_before_parse() { ldfile_output_architecture = bfd_arch_${ARCH}; - config.dynamic_link = true; + config.dynamic_link = ${DYNAMIC_LINK-true}; +} + +/* Try to open a dynamic archive. This is where we know that ELF + dynamic libraries have an extension of .so. */ + +static boolean +gld${EMULATION_NAME}_open_dynamic_archive (arch, entry) + const char *arch; + lang_input_statement_type *entry; +{ + const char *filename; + + filename = entry->filename; + + if (! ldfile_open_file_search (arch, entry, "lib", ".so")) + return false; + + /* We have found a dynamic object to include in the link. The ELF + backend linker will create a DT_NEEDED entry in the .dynamic + section naming this file. If this file includes a DT_SONAME + entry, it will be used. Otherwise, the ELF linker will just use + the name of the file. For an archive found by searching, like + this one, the DT_NEEDED entry should consist of just the name of + the file, without the path information used to find it. Note + that we only need to do this if we have a dynamic object; an + archive will never be referenced by a DT_NEEDED entry. + + FIXME: This approach--using bfd_elf_set_dt_needed_name--is not + very pretty. I haven't been able to think of anything that is + pretty, though. */ + if (bfd_check_format (entry->the_bfd, bfd_object) + && (entry->the_bfd->flags & DYNAMIC) != 0) + { + char *needed_name; + + ASSERT (entry->is_archive && entry->search_dirs_flag); + needed_name = (char *) xmalloc (strlen (filename) + + strlen (arch) + + sizeof "lib.so"); + sprintf (needed_name, "lib%s%s.so", filename, arch); + bfd_elf_set_dt_needed_name (entry->the_bfd, needed_name); + } + + return true; } /* This is called after the sections have been attached to output @@ -68,7 +122,11 @@ gld${EMULATION_NAME}_before_allocation () /* Let the ELF backend work out the sizes of any sections required by dynamic linking. */ - if (! bfd_elf32_size_dynamic_sections (output_bfd, &link_info, + if (! bfd_elf32_size_dynamic_sections (output_bfd, + command_line.soname, + command_line.rpath, + command_line.export_dynamic, + &link_info, &sinterp)) einfo ("%P%F: failed to set dynamic section sizes: %E\n"); @@ -133,6 +191,153 @@ gld${EMULATION_NAME}_find_exp_assignment (exp) } } +/* Place an orphan section. We use this to put random SHF_ALLOC + sections in the right segment. */ + +static asection *hold_section; +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; + +/*ARGSUSED*/ +static boolean +gld${EMULATION_NAME}_place_orphan (file, s) + lang_input_statement_type *file; + asection *s; +{ + lang_output_section_statement_type *place; + asection *snew, **pps; + lang_statement_list_type *old; + lang_statement_list_type add; + etree_type *address; + const char *secname, *ps; + lang_output_section_statement_type *os; + + if ((s->flags & SEC_ALLOC) == 0) + return false; + + /* Look through the script to see where to place this section. */ + hold_section = s; + hold_use = NULL; + lang_for_each_statement (gld${EMULATION_NAME}_place_section); + + if (hold_use != NULL) + { + /* We have already placed a section with this name. */ + wild_doit (&hold_use->children, s, hold_use, file); + return true; + } + + /* Decide which segment the section should go in based on the + section flags. */ + place = NULL; + if ((s->flags & SEC_HAS_CONTENTS) == 0 + && hold_bss != NULL) + place = hold_bss; + else if ((s->flags & SEC_READONLY) == 0 + && hold_data != NULL) + place = hold_data; + 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); + + /* 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. */ + 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; + + /* Start building a list of statements for this section. */ + old = stat_ptr; + stat_ptr = &add; + lang_list_init (stat_ptr); + + /* If the name of the section is representable in C, then create + symbols to mark the start and the end of the section. */ + for (ps = secname; *ps != '\0'; ps++) + if (! isalnum (*ps) && *ps != '_') + break; + if (*ps == '\0' && config.build_constructors) + { + char *symname; + + symname = (char *) xmalloc (ps - secname + sizeof "__start_"); + sprintf (symname, "__start_%s", secname); + lang_add_assignment (exp_assop ('=', symname, + exp_nameop (NAME, "."))); + } + + if (! link_info.relocateable) + address = NULL; + else + address = exp_intop ((bfd_vma) 0); + + lang_enter_output_section_statement (secname, address, 0, + (bfd_vma) 0, + (etree_type *) NULL, + (etree_type *) NULL, + (etree_type *) NULL); + + os = lang_output_section_statement_lookup (secname); + wild_doit (&os->children, s, os, file); + + lang_leave_output_section_statement ((bfd_vma) 0, "*default*"); + stat_ptr = &add; + + if (*ps == '\0' && config.build_constructors) + { + char *symname; + + symname = (char *) xmalloc (ps - secname + sizeof "__stop_"); + sprintf (symname, "__stop_%s", secname); + lang_add_assignment (exp_assop ('=', symname, + exp_nameop (NAME, "."))); + } + + /* Now stick the new statement list right after PLACE. */ + *add.tail = place->header.next; + place->header.next = add.head; + + stat_ptr = old; + + return true; +} + +static void +gld${EMULATION_NAME}_place_section (s) + lang_statement_union_type *s; +{ + lang_output_section_statement_type *os; + + if (s->header.type != lang_output_section_statement_enum) + return; + + os = &s->output_section_statement; + + if (strcmp (os->name, hold_section->name) == 0) + hold_use = os; + + if (strcmp (os->name, ".text") == 0) + hold_text = os; + else if (strcmp (os->name, ".data") == 0) + hold_data = os; + else if (strcmp (os->name, ".bss") == 0) + hold_bss = os; +} + static char * gld${EMULATION_NAME}_get_script(isfile) int *isfile; @@ -161,6 +366,8 @@ cat >>e${EMULATION_NAME}.c <<EOF return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`; else if (!config.magic_demand_paged) return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`; + else if (link_info.shared) + return `sed "$sc" ldscripts/${EMULATION_NAME}.xs`; else return `sed "$sc" ldscripts/${EMULATION_NAME}.x`; } @@ -181,6 +388,8 @@ cat >>e${EMULATION_NAME}.c <<EOF return "ldscripts/${EMULATION_NAME}.xbn"; else if (!config.magic_demand_paged) return "ldscripts/${EMULATION_NAME}.xn"; + else if (link_info.shared) + return "ldscripts/${EMULATION_NAME}.xs"; else return "ldscripts/${EMULATION_NAME}.x"; } @@ -202,6 +411,10 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = gld${EMULATION_NAME}_before_allocation, gld${EMULATION_NAME}_get_script, "${EMULATION_NAME}", - "${OUTPUT_FORMAT}" + "${OUTPUT_FORMAT}", + NULL, + NULL, + gld${EMULATION_NAME}_open_dynamic_archive, + gld${EMULATION_NAME}_place_orphan }; EOF |