]> oss.titaniummirror.com Git - msp430-binutils.git/blobdiff - ld/emultempl/aix.em
Merge commit 'upstream/2.20'
[msp430-binutils.git] / ld / emultempl / aix.em
index 9aa0d500aeea29bcb2f103b9399e13b055851f8b..279032440bd339f14c926f9528d2691c2402e4a9 100644 (file)
@@ -10,7 +10,7 @@ fragment <<EOF
 
 /* AIX emulation code for ${EMULATION_NAME}
    Copyright 1991, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004, 2005, 2006, 2007
+   2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Written by Steve Chamberlain <sac@cygnus.com>
    AIX support by Ian Lance Taylor <ian@cygnus.com>
@@ -84,6 +84,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;
 
@@ -137,6 +145,7 @@ gld${EMULATION_NAME}_before_parse (void)
 {
   ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
 
+  config.dynamic_link = TRUE;
   config.has_shared = TRUE;
 
   /* The link_info.[init|fini]_functions are initialized in ld/lexsup.c.
@@ -155,6 +164,8 @@ enum
     OPTION_AUTOIMP,
     OPTION_ERNOTOK,
     OPTION_EROK,
+    OPTION_EXPALL,
+    OPTION_EXPFULL,
     OPTION_EXPORT,
     OPTION_IMPORT,
     OPTION_INITFINI,
@@ -163,6 +174,8 @@ enum
     OPTION_MAXSTACK,
     OPTION_MODTYPE,
     OPTION_NOAUTOIMP,
+    OPTION_NOEXPALL,
+    OPTION_NOEXPFULL,
     OPTION_NOSTRCMPCT,
     OPTION_PD,
     OPTION_PT,
@@ -200,6 +213,8 @@ 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},
     {"bf", no_argument, NULL, OPTION_ERNOTOK},
     {"bgc", no_argument, &gc, 1},
@@ -215,6 +230,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},
@@ -378,11 +395,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:
@@ -441,6 +470,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;
@@ -575,7 +614,7 @@ gld${EMULATION_NAME}_after_open (void)
      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)
+  if (strstr (bfd_get_target (link_info.output_bfd), "xcoff") != NULL)
     link_info.relocatable = TRUE;
   ldctor_build_sets ();
   link_info.relocatable = r;
@@ -600,7 +639,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");
     }
 }
@@ -615,7 +655,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)
@@ -627,7 +672,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");
     }
 
@@ -701,11 +746,16 @@ gld${EMULATION_NAME}_before_allocation (void)
        }
     }
 
+  /* 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");
 
@@ -823,6 +873,22 @@ gld${EMULATION_NAME}_before_allocation (void)
        }
     }
 
+  /* 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 (!link_info.relocatable)
+    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 ();
 }
 
@@ -1030,32 +1096,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;
@@ -1159,7 +1211,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",
@@ -1206,7 +1259,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");
     }
 
@@ -1232,7 +1286,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);
@@ -1317,7 +1372,7 @@ static void
 gld${EMULATION_NAME}_create_output_section_statements (void)
 {
   /* __rtinit */
-  if ((bfd_get_flavour (output_bfd) == bfd_target_xcoff_flavour)
+  if ((bfd_get_flavour (link_info.output_bfd) == bfd_target_xcoff_flavour)
       && (link_info.init_function != NULL
          || link_info.fini_function != NULL
          || rtld))
@@ -1326,11 +1381,11 @@ gld${EMULATION_NAME}_create_output_section_statements (void)
                                           lang_input_file_is_file_enum,
                                           NULL);
 
-      initfini_file->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;
@@ -1355,13 +1410,38 @@ 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);
+}
 
-  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);
+static bfd_boolean
+gld${EMULATION_NAME}_open_dynamic_archive (const char *arch,
+                                          search_dirs_type *search,
+                                          lang_input_statement_type *entry)
+{
+  const char *filename;
+  char *path;
+
+  if (!entry->is_archive)
+    return FALSE;
+
+  filename = entry->filename;
+  path = concat (search->name, "/lib", entry->filename, arch, ".a", 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 = {
@@ -1379,7 +1459,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = {
   "${OUTPUT_FORMAT}",
   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,