X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=ld%2Femultempl%2Faix.em;h=b9cab4e691cafbaaa95f74cc455fbe4bc601cd8d;hb=29063f8bfb9d68a213efd1d0ab7a66f97ed9a013;hp=513cd50d8594b3cd81c9f402c68ee06d42074727;hpb=5e2f15758b3831ad6fa9f8eee34dbefb689a8d68;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/emultempl/aix.em b/ld/emultempl/aix.em index 513cd50d85..b9cab4e691 100644 --- a/ld/emultempl/aix.em +++ b/ld/emultempl/aix.em @@ -5,36 +5,36 @@ if [ -z "$MACHINE" ]; then else OUTPUT_ARCH=${ARCH}:${MACHINE} fi -cat >e${EMULATION_NAME}.c < AIX support by Ian Lance Taylor AIX 64 bit support by Tom Rix -This file is part of GLD, the Gnu Linker. + This file is part of the GNU Binutils. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ #define TARGET_IS_${EMULATION_NAME} -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "libiberty.h" #include "safe-ctype.h" #include "getopt.h" @@ -82,6 +82,14 @@ static unsigned short modtype = ('1' << 8) | 'L'; permitted). */ static int textro; +/* A mask of XCOFF_EXPALL and XCOFF_EXPFULL flags, as set by their + associated -b and -bno options. */ +static unsigned int auto_export_flags; + +/* A mask of auto_export_flags bits that were explicitly set on the + command line. */ +static unsigned int explicit_auto_export_flags; + /* Whether to implement Unix like linker semantics. */ static int unix_ld; @@ -135,6 +143,7 @@ gld${EMULATION_NAME}_before_parse (void) { ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`); + input_flags.dynamic = TRUE; config.has_shared = TRUE; /* The link_info.[init|fini]_functions are initialized in ld/lexsup.c. @@ -153,6 +162,8 @@ enum OPTION_AUTOIMP, OPTION_ERNOTOK, OPTION_EROK, + OPTION_EXPALL, + OPTION_EXPFULL, OPTION_EXPORT, OPTION_IMPORT, OPTION_INITFINI, @@ -161,6 +172,8 @@ enum OPTION_MAXSTACK, OPTION_MODTYPE, OPTION_NOAUTOIMP, + OPTION_NOEXPALL, + OPTION_NOEXPFULL, OPTION_NOSTRCMPCT, OPTION_PD, OPTION_PT, @@ -198,7 +211,10 @@ gld${EMULATION_NAME}_add_options {"bernotok", no_argument, NULL, OPTION_ERNOTOK}, {"berok", no_argument, NULL, OPTION_EROK}, {"berrmsg", no_argument, NULL, OPTION_IGNORE}, + {"bexpall", no_argument, NULL, OPTION_EXPALL}, + {"bexpfull", no_argument, NULL, OPTION_EXPFULL}, {"bexport", required_argument, NULL, OPTION_EXPORT}, + {"bbigtoc", no_argument, NULL, OPTION_IGNORE}, {"bf", no_argument, NULL, OPTION_ERNOTOK}, {"bgc", no_argument, &gc, 1}, {"bh", required_argument, NULL, OPTION_IGNORE}, @@ -213,6 +229,8 @@ gld${EMULATION_NAME}_add_options {"bM", required_argument, NULL, OPTION_MODTYPE}, {"bmodtype", required_argument, NULL, OPTION_MODTYPE}, {"bnoautoimp", no_argument, NULL, OPTION_NOAUTOIMP}, + {"bnoexpall", no_argument, NULL, OPTION_NOEXPALL}, + {"bnoexpfull", no_argument, NULL, OPTION_NOEXPFULL}, {"bnodelcsect", no_argument, NULL, OPTION_IGNORE}, {"bnoentry", no_argument, NULL, OPTION_IGNORE}, {"bnogc", no_argument, &gc, 0}, @@ -239,7 +257,7 @@ gld${EMULATION_NAME}_add_options {NULL, no_argument, NULL, 0} }; - /* Options supported by the AIX linker which we do not support: -f, + /* Options supported by the AIX linker which we do not support: -S, -v, -Z, -bbindcmds, -bbinder, -bbindopts, -bcalls, -bcaps, -bcror15, -bdebugopt, -bdbg, -bdelcsect, -bex?, -bfilelist, -bfl, -bgcbypass, -bglink, -binsert, -bi, -bloadmap, -bl, -bmap, -bnl, @@ -267,7 +285,7 @@ gld${EMULATION_NAME}_parse_args (int argc, char **argv) if (indx == 0) indx = 1; - if (indx < argc && strncmp (argv[indx], "-b", 2) == 0) + if (indx < argc && CONST_STRNEQ (argv[indx], "-b")) { char *s; @@ -283,6 +301,76 @@ gld${EMULATION_NAME}_parse_args (int argc, char **argv) return FALSE; } +/* Helper for option '-f', which specify a list of input files. + Contrary to the native linker, we don't support shell patterns + (simply because glob isn't always available). */ + +static void +read_file_list (const char *filename) +{ + FILE *f; + /* An upper bound on the number of characters in the file. */ + long pos; + /* File in memory. */ + char *buffer; + size_t len; + char *b; + char *e; + + f = fopen (filename, FOPEN_RT); + if (f == NULL) + { + einfo ("%F%P: cannot open %s\n", filename); + return; + } + if (fseek (f, 0L, SEEK_END) == -1) + goto error; + pos = ftell (f); + if (pos == -1) + goto error; + if (fseek (f, 0L, SEEK_SET) == -1) + goto error; + + buffer = (char *) xmalloc (pos + 1); + len = fread (buffer, sizeof (char), pos, f); + if (len != (size_t) pos && ferror (f)) + goto error; + /* Add a NUL terminator. */ + buffer[len] = '\0'; + fclose (f); + + /* Parse files. */ + b = buffer; + while (1) + { + /* Skip empty lines. */ + while (*b == '\n' || *b == '\r') + b++; + + /* Stop if end of buffer. */ + if (b == buffer + len) + break; + + /* Eat any byte until end of line. */ + for (e = b; *e != '\0'; e++) + if (*e == '\n' || *e == '\r') + break; + + /* Replace end of line by nul. */ + if (*e != '\0') + *e++ = '\0'; + + if (b != e) + lang_add_input_file (b, lang_input_file_is_search_file_enum, NULL); + b = e; + } + return; + + error: + einfo ("%F%P: cannot read %s\n", optarg); + fclose (f); +} + static bfd_boolean gld${EMULATION_NAME}_handle_option (int optc) { @@ -298,12 +386,18 @@ gld${EMULATION_NAME}_handle_option (int optc) /* Long option which just sets a flag. */ break; + case 'f': + /* This overrides --auxiliary. This option specifies a file containing + a list of input files. */ + read_file_list (optarg); + break; + case 'D': val = bfd_scan_vma (optarg, &end, 0); if (*end != '\0') einfo ("%P: warning: ignoring invalid -D number %s\n", optarg); else if (val != -1) - lang_section_start (".data", exp_intop (val)); + lang_section_start (".data", exp_intop (val), NULL); break; case 'H': @@ -328,7 +422,7 @@ gld${EMULATION_NAME}_handle_option (int optc) val = bfd_scan_vma (optarg, &end, 0); if (*end != '\0') return FALSE; - lang_section_start (".text", exp_intop (val)); + lang_section_start (".text", exp_intop (val), NULL); break; case OPTION_IGNORE: @@ -376,11 +470,23 @@ gld${EMULATION_NAME}_handle_option (int optc) break; case OPTION_ERNOTOK: - force_make_executable = FALSE; + link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR; + link_info.unresolved_syms_in_shared_libs = RM_GENERATE_ERROR; break; case OPTION_EROK: - force_make_executable = TRUE; + link_info.unresolved_syms_in_objects = RM_IGNORE; + link_info.unresolved_syms_in_shared_libs = RM_IGNORE; + break; + + case OPTION_EXPALL: + auto_export_flags |= XCOFF_EXPALL; + explicit_auto_export_flags |= XCOFF_EXPALL; + break; + + case OPTION_EXPFULL: + auto_export_flags |= XCOFF_EXPFULL; + explicit_auto_export_flags |= XCOFF_EXPFULL; break; case OPTION_EXPORT: @@ -426,7 +532,7 @@ gld${EMULATION_NAME}_handle_option (int optc) case OPTION_MODTYPE: if (*optarg == 'S') { - link_info.shared = TRUE; + link_info.type = type_dll; ++optarg; } if (*optarg == '\0' || optarg[1] == '\0') @@ -439,6 +545,16 @@ gld${EMULATION_NAME}_handle_option (int optc) link_info.static_link = TRUE; break; + case OPTION_NOEXPALL: + auto_export_flags &= ~XCOFF_EXPALL; + explicit_auto_export_flags |= XCOFF_EXPALL; + break; + + case OPTION_NOEXPFULL: + auto_export_flags &= ~XCOFF_EXPFULL; + explicit_auto_export_flags |= XCOFF_EXPFULL; + break; + case OPTION_NOSTRCMPCT: link_info.traditional_format = TRUE; break; @@ -463,7 +579,7 @@ gld${EMULATION_NAME}_handle_option (int optc) t = exp_binop ('&', exp_binop ('+', t, exp_intop (31)), exp_intop (~(bfd_vma) 31)); - lang_section_start (".data", t); + lang_section_start (".data", t, NULL); } break; @@ -484,7 +600,7 @@ gld${EMULATION_NAME}_handle_option (int optc) t = exp_binop ('&', exp_binop ('+', t, exp_intop (31)), exp_intop (~(bfd_vma) 31)); - lang_section_start (".text", t); + lang_section_start (".text", t, NULL); } break; @@ -551,7 +667,7 @@ gld${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry) *flpp = n; ret = TRUE; - entry->loaded = TRUE; + entry->flags.loaded = TRUE; } fclose (e); @@ -564,19 +680,21 @@ gld${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry) static void gld${EMULATION_NAME}_after_open (void) { - bfd_boolean r; + enum output_type t; struct set_info *p; + after_open_default (); + /* Call ldctor_build_sets, after pretending that this is a relocatable link. We do this because AIX requires relocation entries for all references to symbols, even in a final executable. Of course, we only want to do this if we are producing an XCOFF output file. */ - r = link_info.relocatable; - if (strstr (bfd_get_target (output_bfd), "xcoff") != NULL) - link_info.relocatable = TRUE; + t = link_info.type; + if (strstr (bfd_get_target (link_info.output_bfd), "xcoff") != NULL) + link_info.type = type_relocatable; ldctor_build_sets (); - link_info.relocatable = r; + link_info.type = t; /* For each set, record the size, so that the XCOFF backend can output the correct csect length. */ @@ -598,7 +716,8 @@ gld${EMULATION_NAME}_after_open (void) } size = (p->count + 2) * 4; - if (!bfd_xcoff_link_record_set (output_bfd, &link_info, p->h, size)) + if (!bfd_xcoff_link_record_set (link_info.output_bfd, &link_info, + p->h, size)) einfo ("%F%P: bfd_xcoff_link_record_set failed: %E\n"); } } @@ -613,7 +732,12 @@ gld${EMULATION_NAME}_before_allocation (void) struct export_symbol_list *el; char *libpath; asection *special_sections[XCOFF_NUMBER_OF_SPECIAL_SECTIONS]; - int i; + static const char *const must_keep_sections[] = { + ".text", + ".data", + ".bss" + }; + unsigned int i, flags; /* Handle the import and export files, if any. */ for (fl = import_files; fl != NULL; fl = fl->next) @@ -625,7 +749,7 @@ gld${EMULATION_NAME}_before_allocation (void) h = bfd_link_hash_lookup (link_info.hash, el->name, FALSE, FALSE, FALSE); if (h == NULL) einfo ("%P%F: bfd_link_hash_lookup of export symbol failed: %E\n"); - if (!bfd_xcoff_export_symbol (output_bfd, &link_info, h)) + if (!bfd_xcoff_export_symbol (link_info.output_bfd, &link_info, h)) einfo ("%P%F: bfd_xcoff_export_symbol failed: %E\n"); } @@ -650,26 +774,65 @@ gld${EMULATION_NAME}_before_allocation (void) size_t len; search_dirs_type *search; - len = strlen (search_head->name); - libpath = xmalloc (len + 1); - strcpy (libpath, search_head->name); - for (search = search_head->next; search != NULL; search = search->next) + /* PR ld/4023: Strip sysroot prefix from any paths + being inserted into the output binary's DT_RPATH. */ + if (ld_sysroot != NULL + && * ld_sysroot != 0) { - size_t nlen; + const char * name = search_head->name; + size_t ld_sysroot_len = strlen (ld_sysroot); + + if (strncmp (name, ld_sysroot, ld_sysroot_len) == 0) + name += ld_sysroot_len; + + len = strlen (name); + libpath = xmalloc (len + 1); + strcpy (libpath, name); - nlen = strlen (search->name); - libpath = xrealloc (libpath, len + nlen + 2); - libpath[len] = ':'; - strcpy (libpath + len + 1, search->name); - len += nlen + 1; + for (search = search_head->next; search != NULL; search = search->next) + { + size_t nlen; + + name = search->name; + if (strncmp (name, ld_sysroot, ld_sysroot_len) == 0) + name += ld_sysroot_len; + + nlen = strlen (name); + libpath = xrealloc (libpath, len + nlen + 2); + libpath[len] = ':'; + strcpy (libpath + len + 1, name); + len += nlen + 1; + } + } + else + { + len = strlen (search_head->name); + libpath = xmalloc (len + 1); + strcpy (libpath, search_head->name); + + for (search = search_head->next; search != NULL; search = search->next) + { + size_t nlen; + + nlen = strlen (search->name); + libpath = xrealloc (libpath, len + nlen + 2); + libpath[len] = ':'; + strcpy (libpath + len + 1, search->name); + len += nlen + 1; + } } } + /* Default to -bexpfull for SVR4-like semantics. */ + flags = (unix_ld ? XCOFF_EXPFULL : 0); + flags &= ~explicit_auto_export_flags; + flags |= auto_export_flags; + /* Let the XCOFF backend set up the .loader section. */ if (!bfd_xcoff_size_dynamic_sections - (output_bfd, &link_info, libpath, entry_symbol.name, file_align, + (link_info.output_bfd, &link_info, libpath, entry_symbol.name, file_align, maxstack, maxdata, gc && !unix_ld ? TRUE : FALSE, - modtype, textro ? TRUE : FALSE, unix_ld, special_sections, + modtype, textro ? TRUE : FALSE, flags, special_sections, rtld ? TRUE : FALSE)) einfo ("%P%F: failed to set dynamic section sizes: %E\n"); @@ -691,7 +854,7 @@ gld${EMULATION_NAME}_before_allocation (void) /* Remove this section from the list of the output section. This assumes we know what the script looks like. */ is = NULL; - os = lang_output_section_find (sec->output_section->name); + os = lang_output_section_get (sec->output_section); if (os == NULL) einfo ("%P%F: can't find output section %s\n", sec->output_section->name); @@ -786,6 +949,24 @@ gld${EMULATION_NAME}_before_allocation (void) &is->header.next); } } + + /* Executables and shared objects must always have .text, .data + and .bss output sections, so that the header can refer to them. + The kernel refuses to load objects that have missing sections. */ + if (!bfd_link_relocatable (&link_info)) + for (i = 0; i < ARRAY_SIZE (must_keep_sections); i++) + { + asection *sec; + + sec = bfd_get_section_by_name (link_info.output_bfd, + must_keep_sections[i]); + if (sec == NULL) + einfo ("%P: can't find required output section %s\n", must_keep_sections[i]); + else + sec->flags |= SEC_KEEP; + } + + before_allocation_default (); } static char * @@ -927,6 +1108,7 @@ gld${EMULATION_NAME}_read_file (const char *filename, bfd_boolean import) { bfd_set_error (bfd_error_system_call); einfo ("%F%s: %E\n", filename); + return; } keep = FALSE; @@ -992,32 +1174,18 @@ gld${EMULATION_NAME}_read_file (const char *filename, bfd_boolean import) else { char cs; - char *file; + char *start; (void) obstack_finish (o); keep = TRUE; - imppath = s; - file = NULL; + start = s; while (!ISSPACE (*s) && *s != '(' && *s != '\0') - { - if (*s == '/') - file = s + 1; - ++s; - } - if (file != NULL) - { - file[-1] = '\0'; - impfile = file; - if (imppath == file - 1) - imppath = "/"; - } - else - { - impfile = imppath; - imppath = ""; - } + ++s; cs = *s; *s = '\0'; + if (!bfd_xcoff_split_import_path (link_info.output_bfd, + start, &imppath, &impfile)) + einfo ("%F%P: Could not parse import path: %E\n"); while (ISSPACE (cs)) { ++s; @@ -1103,7 +1271,7 @@ gld${EMULATION_NAME}_read_file (const char *filename, bfd_boolean import) { struct export_symbol_list *n; - ldlang_add_undef (symname); + ldlang_add_undef (symname, TRUE); n = ((struct export_symbol_list *) xmalloc (sizeof (struct export_symbol_list))); n->next = export_symbols; @@ -1121,7 +1289,8 @@ gld${EMULATION_NAME}_read_file (const char *filename, bfd_boolean import) } else { - if (!bfd_xcoff_import_symbol (output_bfd, &link_info, h, + if (!bfd_xcoff_import_symbol (link_info.output_bfd, + &link_info, h, address, imppath, impfile, impmember, syscall_flag)) einfo ("%X%s:%d: failed to import symbol %s: %E\n", @@ -1144,6 +1313,8 @@ gld${EMULATION_NAME}_read_file (const char *filename, bfd_boolean import) obstack_free (o, NULL); free (o); } + + fclose (f); } /* This routine saves us from worrying about declaring free. */ @@ -1168,7 +1339,8 @@ gld${EMULATION_NAME}_find_relocs (lang_statement_union_type *s) rs = &s->reloc_statement; if (rs->name == NULL) einfo ("%F%P: only relocations against symbols are permitted\n"); - if (!bfd_xcoff_link_count_reloc (output_bfd, &link_info, rs->name)) + if (!bfd_xcoff_link_count_reloc (link_info.output_bfd, &link_info, + rs->name)) einfo ("%F%P: bfd_xcoff_link_count_reloc failed: %E\n"); } @@ -1194,7 +1366,8 @@ gld${EMULATION_NAME}_find_exp_assignment (etree_type *exp) case etree_assign: if (strcmp (exp->assign.dst, ".") != 0) { - if (!bfd_xcoff_record_link_assignment (output_bfd, &link_info, + if (!bfd_xcoff_record_link_assignment (link_info.output_bfd, + &link_info, exp->assign.dst)) einfo ("%P%F: failed to record assignment to %s: %E\n", exp->assign.dst); @@ -1226,22 +1399,22 @@ static char * gld${EMULATION_NAME}_get_script (int *isfile) EOF -if test -n "$COMPILE_IN" +if test x"$COMPILE_IN" = xyes then # Scripts compiled in. # sed commands to quote an ld script as a C string. sc="-f ${srcdir}/emultempl/ostring.sed" -cat >>e${EMULATION_NAME}.c <> e${EMULATION_NAME}.c -echo ' ; else if (link_info.relocatable) return' >> e${EMULATION_NAME}.c +echo ' ; else if (bfd_link_relocatable (&link_info)) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c @@ -1254,13 +1427,13 @@ echo '; }' >> e${EMULATION_NAME}.c else # Scripts read from the filesystem. -cat >>e${EMULATION_NAME}.c <>e${EMULATION_NAME}.c <the_bfd = bfd_create ("initfini", output_bfd); + initfini_file->the_bfd = bfd_create ("initfini", link_info.output_bfd); if (initfini_file->the_bfd == NULL || ! bfd_set_arch_mach (initfini_file->the_bfd, - bfd_get_arch (output_bfd), - bfd_get_mach (output_bfd))) + bfd_get_arch (link_info.output_bfd), + bfd_get_mach (link_info.output_bfd))) { einfo ("%X%P: can not create BFD %E\n"); return; @@ -1317,13 +1490,42 @@ gld${EMULATION_NAME}_create_output_section_statements (void) static void gld${EMULATION_NAME}_set_output_arch (void) { - bfd_set_arch_mach (output_bfd, - bfd_xcoff_architecture (output_bfd), - bfd_xcoff_machine (output_bfd)); + bfd_set_arch_mach (link_info.output_bfd, + bfd_xcoff_architecture (link_info.output_bfd), + bfd_xcoff_machine (link_info.output_bfd)); + + ldfile_output_architecture = bfd_get_arch (link_info.output_bfd); + ldfile_output_machine = bfd_get_mach (link_info.output_bfd); + ldfile_output_machine_name = bfd_printable_name (link_info.output_bfd); +} + +static bfd_boolean +gld${EMULATION_NAME}_open_dynamic_archive (const char *arch, + search_dirs_type *search, + lang_input_statement_type *entry) +{ + char *path; - ldfile_output_architecture = bfd_get_arch (output_bfd); - ldfile_output_machine = bfd_get_mach (output_bfd); - ldfile_output_machine_name = bfd_printable_name (output_bfd); + if (!entry->flags.maybe_archive) + return FALSE; + + if (entry->flags.full_name_provided) + path = concat (search->name, "/", entry->filename, + (const char *) NULL); + else + path = concat (search->name, "/lib", entry->filename, arch, ".a", + (const char *) NULL); + + if (!ldfile_try_open_bfd (path, entry)) + { + free (path); + return FALSE; + } + /* Don't include the searched directory in the import path. */ + bfd_xcoff_set_archive_import_path (&link_info, entry->the_bfd, + path + strlen (search->name) + 1); + entry->filename = path; + return TRUE; } struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = { @@ -1339,9 +1541,9 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = { gld${EMULATION_NAME}_get_script, "${EMULATION_NAME}", "${OUTPUT_FORMAT}", - 0, /* finish */ + finish_default, gld${EMULATION_NAME}_create_output_section_statements, - 0, /* open_dynamic_archive */ + gld${EMULATION_NAME}_open_dynamic_archive, 0, /* place_orphan */ 0, /* set_symbols */ gld${EMULATION_NAME}_parse_args, @@ -1351,6 +1553,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = { NULL, /* list_options */ NULL, /* recognized_file */ NULL, /* find potential_libraries */ - NULL /* new_vers_pattern */ + NULL, /* new_vers_pattern */ + NULL /* extra_map_file_text */ }; EOF