* ld-elf/orphan-region.d: Use ld -N.
[binutils-gdb.git] / ld / lexsup.c
index 1e133d9f9a51c747d4b9e38173fd6489aff7003d..b992fca37ab13cdb9ddf4be677304b5777035ad2 100644 (file)
@@ -1,6 +1,6 @@
 /* Parse options for the GNU linker.
    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils.
@@ -77,6 +77,7 @@ enum option_values
   OPTION_EL,
   OPTION_EMBEDDED_RELOCS,
   OPTION_EXPORT_DYNAMIC,
+  OPTION_NO_EXPORT_DYNAMIC,
   OPTION_HELP,
   OPTION_IGNORE,
   OPTION_MAP,
@@ -89,6 +90,7 @@ enum option_values
   OPTION_NO_WHOLE_ARCHIVE,
   OPTION_OFORMAT,
   OPTION_RELAX,
+  OPTION_NO_RELAX,
   OPTION_RETAIN_SYMBOLS_FILE,
   OPTION_RPATH,
   OPTION_RPATH_LINK,
@@ -103,6 +105,7 @@ enum option_values
   OPTION_TBSS,
   OPTION_TDATA,
   OPTION_TTEXT,
+  OPTION_TTEXT_SEGMENT,
   OPTION_TRADITIONAL_FORMAT,
   OPTION_UR,
   OPTION_VERBOSE,
@@ -116,16 +119,17 @@ enum option_values
   OPTION_WARN_COMMON,
   OPTION_WARN_CONSTRUCTORS,
   OPTION_WARN_FATAL,
+  OPTION_NO_WARN_FATAL,
   OPTION_WARN_MULTIPLE_GP,
   OPTION_WARN_ONCE,
   OPTION_WARN_SECTION_ALIGN,
   OPTION_SPLIT_BY_RELOC,
   OPTION_SPLIT_BY_FILE ,
   OPTION_WHOLE_ARCHIVE,
-  OPTION_ADD_NEEDED,
-  OPTION_NO_ADD_NEEDED,
-  OPTION_AS_NEEDED,
-  OPTION_NO_AS_NEEDED,
+  OPTION_ADD_DT_NEEDED_FOR_DYNAMIC,
+  OPTION_NO_ADD_DT_NEEDED_FOR_DYNAMIC,
+  OPTION_ADD_DT_NEEDED_FOR_REGULAR,
+  OPTION_NO_ADD_DT_NEEDED_FOR_REGULAR,
   OPTION_WRAP,
   OPTION_FORCE_EXE_SUFFIX,
   OPTION_GC_SECTIONS,
@@ -161,6 +165,7 @@ enum option_values
   OPTION_WARN_UNRESOLVED_SYMBOLS,
   OPTION_ERROR_UNRESOLVED_SYMBOLS,
   OPTION_WARN_SHARED_TEXTREL,
+  OPTION_WARN_ALTERNATE_EM,
   OPTION_REDUCE_MEMORY_OVERHEADS,
   OPTION_DEFAULT_SCRIPT
 };
@@ -168,6 +173,25 @@ enum option_values
 /* The long options.  This structure is used for both the option
    parsing and the help text.  */
 
+enum control_enum {
+  /* Use one dash before long option name.  */
+  ONE_DASH,
+  /* Use two dashes before long option name.  */
+  TWO_DASHES,
+  /* Only accept two dashes before the long option name.
+     This is an overloading of the use of this enum, since originally it
+     was only intended to tell the --help display function how to display
+     the long option name.  This feature was added in order to resolve
+     the confusion about the -omagic command line switch.  Is it setting
+     the output file name to "magic" or is it setting the NMAGIC flag on
+     the output ?  It has been decided that it is setting the output file
+     name, and that if you want to set the NMAGIC flag you should use -N
+     or --omagic.  */
+  EXACTLY_TWO_DASHES,
+  /* Don't mention this option in --help output.  */
+  NO_HELP
+};
+
 struct ld_option
 {
   /* The long option information.  */
@@ -179,24 +203,7 @@ struct ld_option
   /* The documentation string.  If this is NULL, this is a synonym for
      the previous option.  */
   const char *doc;
-  enum {
-    /* Use one dash before long option name.  */
-    ONE_DASH,
-    /* Use two dashes before long option name.  */
-    TWO_DASHES,
-    /* Only accept two dashes before the long option name.
-       This is an overloading of the use of this enum, since originally it
-       was only intended to tell the --help display function how to display
-       the long option name.  This feature was added in order to resolve
-       the confusion about the -omagic command line switch.  Is it setting
-       the output file name to "magic" or is it setting the NMAGIC flag on
-       the output ?  It has been decided that it is setting the output file
-       name, and that if you want to set the NMAGIC flag you should use -N
-       or --omagic.  */
-    EXACTLY_TWO_DASHES,
-    /* Don't mention this option in --help output.  */
-    NO_HELP
-  } control;
+  enum control_enum control;
 };
 
 static const struct ld_option ld_options[] =
@@ -219,6 +226,8 @@ static const struct ld_option ld_options[] =
     'e', N_("ADDRESS"), N_("Set start address"), TWO_DASHES },
   { {"export-dynamic", no_argument, NULL, OPTION_EXPORT_DYNAMIC},
     'E', NULL, N_("Export all dynamic symbols"), TWO_DASHES },
+  { {"no-export-dynamic", no_argument, NULL, OPTION_NO_EXPORT_DYNAMIC},
+    '\0', NULL, N_("Undo the effect of --export-dynamic"), TWO_DASHES },
   { {"EB", no_argument, NULL, OPTION_EB},
     '\0', NULL, N_("Link big-endian objects"), ONE_DASH },
   { {"EL", no_argument, NULL, OPTION_EL},
@@ -325,19 +334,22 @@ static const struct ld_option ld_options[] =
      OPTION_NO_ACCEPT_UNKNOWN_INPUT_ARCH},
     '\0', NULL, N_("Reject input files whose architecture is unknown"),
     TWO_DASHES },
-  { {"add-needed", no_argument, NULL, OPTION_ADD_NEEDED},
-    '\0', NULL, N_("Set DT_NEEDED tags for DT_NEEDED entries in\n"
-                  "                                following dynamic libs"),
-    TWO_DASHES },
-  { {"no-add-needed", no_argument, NULL, OPTION_NO_ADD_NEEDED},
-    '\0', NULL, N_("Do not set DT_NEEDED tags for DT_NEEDED entries\n"
-                  "                                in following dynamic libs"),
-    TWO_DASHES },
-  { {"as-needed", no_argument, NULL, OPTION_AS_NEEDED},
+
+  /* The next two options are deprecated because of their similarity to
+     --as-needed and --no-as-needed.  They have been replaced by
+     --resolve-implicit-dynamic-symbols and
+     --no-resolve-implicit-dynamic-symbols.  */
+  { {"add-needed", no_argument, NULL, OPTION_ADD_DT_NEEDED_FOR_DYNAMIC},
+    '\0', NULL, NULL, NO_HELP },
+  { {"no-add-needed", no_argument, NULL, OPTION_NO_ADD_DT_NEEDED_FOR_DYNAMIC},
+    '\0', NULL, NULL, NO_HELP },
+
+  { {"as-needed", no_argument, NULL, OPTION_ADD_DT_NEEDED_FOR_REGULAR},
     '\0', NULL, N_("Only set DT_NEEDED for following dynamic libs if used"),
     TWO_DASHES },
-  { {"no-as-needed", no_argument, NULL, OPTION_NO_AS_NEEDED},
-    '\0', NULL, N_("Always set DT_NEEDED for following dynamic libs"),
+  { {"no-as-needed", no_argument, NULL, OPTION_NO_ADD_DT_NEEDED_FOR_REGULAR},
+    '\0', NULL, N_("Always set DT_NEEDED for dynamic libraries mentioned on\n"
+                  "                                the command line"),
     TWO_DASHES },
   { {"assert", required_argument, NULL, OPTION_ASSERT},
     '\0', N_("KEYWORD"), N_("Ignored for SunOS compatibility"), ONE_DASH },
@@ -365,6 +377,15 @@ static const struct ld_option ld_options[] =
   { {"no-check-sections", no_argument, NULL, OPTION_NO_CHECK_SECTIONS},
     '\0', NULL, N_("Do not check section addresses for overlaps"),
     TWO_DASHES },
+  { {"copy-dt-needed-entries", no_argument, NULL,
+     OPTION_ADD_DT_NEEDED_FOR_DYNAMIC},
+    '\0', NULL, N_("Copy DT_NEEDED links mentioned inside DSOs that follow"),
+    TWO_DASHES },
+  { {"no-copy-dt-needed-entries", no_argument, NULL,
+     OPTION_NO_ADD_DT_NEEDED_FOR_DYNAMIC},
+    '\0', NULL, N_("Do not copy DT_NEEDED links mentioned inside DSOs that follow"),
+    TWO_DASHES },
+
   { {"cref", no_argument, NULL, OPTION_CREF},
     '\0', NULL, N_("Output cross reference table"), TWO_DASHES },
   { {"defsym", required_argument, NULL, OPTION_DEFSYM},
@@ -377,6 +398,9 @@ static const struct ld_option ld_options[] =
   { {"fatal-warnings", no_argument, NULL, OPTION_WARN_FATAL},
     '\0', NULL, N_("Treat warnings as errors"),
     TWO_DASHES },
+  { {"no-fatal-warnings", no_argument, NULL, OPTION_NO_WARN_FATAL},
+    '\0', NULL, N_("Do not treat warnings as errors (default)"),
+    TWO_DASHES },
   { {"fini", required_argument, NULL, OPTION_FINI},
     '\0', N_("SYMBOL"), N_("Call SYMBOL at unload-time"), ONE_DASH },
   { {"force-exe-suffix", no_argument, NULL, OPTION_FORCE_EXE_SUFFIX},
@@ -456,7 +480,9 @@ static const struct ld_option ld_options[] =
     '\0', NULL, N_("Reduce memory overheads, possibly taking much longer"),
     TWO_DASHES },
   { {"relax", no_argument, NULL, OPTION_RELAX},
-    '\0', NULL, N_("Relax branches on certain targets"), TWO_DASHES },
+    '\0', NULL, N_("Reduce code size by using target specific optimizations"), TWO_DASHES },
+  { {"no-relax", no_argument, NULL, OPTION_NO_RELAX},
+    '\0', NULL, N_("Do not use relaxation techniques to reduce code size"), TWO_DASHES },
   { {"retain-symbols-file", required_argument, NULL,
      OPTION_RETAIN_SYMBOLS_FILE},
     '\0', N_("FILE"), N_("Keep only symbols listed in FILE"), TWO_DASHES },
@@ -473,8 +499,10 @@ static const struct ld_option ld_options[] =
     '\0', NULL, N_("Create a position independent executable"), ONE_DASH },
   { {"pic-executable", no_argument, NULL, OPTION_PIE},
     '\0', NULL, NULL, TWO_DASHES },
-  { {"sort-common", no_argument, NULL, OPTION_SORT_COMMON},
-    '\0', NULL, N_("Sort common symbols by size"), TWO_DASHES },
+  { {"sort-common", optional_argument, NULL, OPTION_SORT_COMMON},
+    '\0', N_("[=ascending|descending]"), 
+    N_("Sort common symbols by alignment [in specified order]"), 
+    TWO_DASHES },
   { {"sort_common", no_argument, NULL, OPTION_SORT_COMMON},
     '\0', NULL, NULL, NO_HELP },
   { {"sort-section", required_argument, NULL, OPTION_SORT_SECTION},
@@ -506,6 +534,8 @@ static const struct ld_option ld_options[] =
     '\0', N_("ADDRESS"), N_("Set address of .data section"), ONE_DASH },
   { {"Ttext", required_argument, NULL, OPTION_TTEXT},
     '\0', N_("ADDRESS"), N_("Set address of .text section"), ONE_DASH },
+  { {"Ttext-segment", required_argument, NULL, OPTION_TTEXT_SEGMENT},
+    '\0', N_("ADDRESS"), N_("Set address of text segment"), ONE_DASH },
   { {"unresolved-symbols=<method>", required_argument, NULL,
      OPTION_UNRESOLVED_SYMBOLS},
     '\0', NULL, N_("How to handle unresolved symbols.  <method> is:\n"
@@ -546,6 +576,9 @@ static const struct ld_option ld_options[] =
   { {"warn-shared-textrel", no_argument, NULL, OPTION_WARN_SHARED_TEXTREL},
     '\0', NULL, N_("Warn if shared object has DT_TEXTREL"),
     TWO_DASHES },
+  { {"warn-alternate-em", no_argument, NULL, OPTION_WARN_ALTERNATE_EM},
+    '\0', NULL, N_("Warn if an object has alternate ELF machine code"),
+    TWO_DASHES },
   { {"warn-unresolved-symbols", no_argument, NULL,
      OPTION_WARN_UNRESOLVED_SYMBOLS},
     '\0', NULL, N_("Report unresolved symbols as warnings"), TWO_DASHES },
@@ -574,9 +607,11 @@ parse_args (unsigned argc, char **argv)
   int last_optind;
   enum report_method how_to_report_unresolved_symbols = RM_GENERATE_ERROR;
 
-  shortopts = xmalloc (OPTION_COUNT * 3 + 2);
-  longopts = xmalloc (sizeof (*longopts) * (OPTION_COUNT + 1));
-  really_longopts = xmalloc (sizeof (*really_longopts) * (OPTION_COUNT + 1));
+  shortopts = (char *) xmalloc (OPTION_COUNT * 3 + 2);
+  longopts = (struct option *)
+      xmalloc (sizeof (*longopts) * (OPTION_COUNT + 1));
+  really_longopts = (struct option *)
+      malloc (sizeof (*really_longopts) * (OPTION_COUNT + 1));
 
   /* Starting the short option string with '-' is for programs that
      expect options and other ARGV-elements in any order and that care about
@@ -661,7 +696,7 @@ parse_args (unsigned argc, char **argv)
        {
          char *n;
 
-         n = xmalloc (strlen (argv[i]) + 20);
+         n = (char *) xmalloc (strlen (argv[i]) + 20);
          sprintf (n, "--library=%s", argv[i] + 2);
          argv[i] = n;
        }
@@ -807,13 +842,17 @@ parse_args (unsigned argc, char **argv)
        case 'E': /* HP/UX compatibility.  */
          link_info.export_dynamic = TRUE;
          break;
+       case OPTION_NO_EXPORT_DYNAMIC:
+         link_info.export_dynamic = FALSE;
+         break;
        case 'e':
          lang_add_entry (optarg, TRUE);
          break;
        case 'f':
          if (command_line.auxiliary_filters == NULL)
            {
-             command_line.auxiliary_filters = xmalloc (2 * sizeof (char *));
+             command_line.auxiliary_filters = (char **)
+                  xmalloc (2 * sizeof (char *));
              command_line.auxiliary_filters[0] = optarg;
              command_line.auxiliary_filters[1] = NULL;
            }
@@ -825,8 +864,8 @@ parse_args (unsigned argc, char **argv)
              c = 0;
              for (p = command_line.auxiliary_filters; *p != NULL; p++)
                ++c;
-             command_line.auxiliary_filters
-               = xrealloc (command_line.auxiliary_filters,
+             command_line.auxiliary_filters = (char **)
+                  xrealloc (command_line.auxiliary_filters,
                            (c + 2) * sizeof (char *));
              command_line.auxiliary_filters[c] = optarg;
              command_line.auxiliary_filters[c + 1] = NULL;
@@ -1072,7 +1111,7 @@ parse_args (unsigned argc, char **argv)
 
              if (cp == NULL)
                {
-                 buf = xmalloc (rpath_len + optarg_len + 2);
+                 buf = (char *) xmalloc (rpath_len + optarg_len + 2);
                  sprintf (buf, "%s%c%s", command_line.rpath,
                           config.rpath_separator, optarg);
                  free (command_line.rpath);
@@ -1087,17 +1126,20 @@ parse_args (unsigned argc, char **argv)
            {
              char *buf;
 
-             buf = xmalloc (strlen (command_line.rpath_link)
-                            + strlen (optarg)
-                            + 2);
+             buf = (char *) xmalloc (strlen (command_line.rpath_link)
+                                      + strlen (optarg)
+                                      + 2);
              sprintf (buf, "%s%c%s", command_line.rpath_link,
                       config.rpath_separator, optarg);
              free (command_line.rpath_link);
              command_line.rpath_link = buf;
            }
          break;
+       case OPTION_NO_RELAX:
+         DISABLE_RELAXATION;
+         break;
        case OPTION_RELAX:
-         command_line.relax = TRUE;
+         ENABLE_RELAXATION;
          break;
        case OPTION_RETAIN_SYMBOLS_FILE:
          add_keepsyms_file (optarg);
@@ -1142,7 +1184,14 @@ parse_args (unsigned argc, char **argv)
          command_line.soname = optarg;
          break;
        case OPTION_SORT_COMMON:
-         config.sort_common = TRUE;
+         if (optarg == NULL
+             || strcmp (optarg, N_("descending")) == 0)
+            config.sort_common = sort_descending;
+          else if (strcmp (optarg, N_("ascending")) == 0)
+           config.sort_common = sort_ascending;
+         else
+           einfo (_("%P%F: invalid common section sorting option: %s\n"),
+                  optarg);
          break;
        case OPTION_SORT_SECTION:
          if (strcmp (optarg, N_("name")) == 0)
@@ -1197,7 +1246,7 @@ parse_args (unsigned argc, char **argv)
            /* We must copy the section name as set_section_start
               doesn't do it for us.  */
            len = optarg2 - optarg;
-           sec_name = xmalloc (len);
+           sec_name = (char *) xmalloc (len);
            memcpy (sec_name, optarg, len - 1);
            sec_name[len - 1] = 0;
 
@@ -1218,6 +1267,9 @@ parse_args (unsigned argc, char **argv)
        case OPTION_TTEXT:
          set_segment_start (".text", optarg);
          break;
+       case OPTION_TTEXT_SEGMENT:
+         set_segment_start (".text-segment", optarg);
+         break;
        case OPTION_TRADITIONAL_FORMAT:
          link_info.traditional_format = TRUE;
          break;
@@ -1324,6 +1376,9 @@ parse_args (unsigned argc, char **argv)
        case OPTION_WARN_FATAL:
          config.fatal_warnings = TRUE;
          break;
+       case OPTION_NO_WARN_FATAL:
+         config.fatal_warnings = FALSE;
+         break;
        case OPTION_WARN_MULTIPLE_GP:
          config.warn_multiple_gp = TRUE;
          break;
@@ -1336,20 +1391,23 @@ parse_args (unsigned argc, char **argv)
        case OPTION_WARN_SHARED_TEXTREL:
          link_info.warn_shared_textrel = TRUE;
          break;
+       case OPTION_WARN_ALTERNATE_EM:
+         link_info.warn_alternate_em = TRUE;
+         break;
        case OPTION_WHOLE_ARCHIVE:
          whole_archive = TRUE;
          break;
-       case OPTION_ADD_NEEDED:
-         add_needed = TRUE;
+       case OPTION_ADD_DT_NEEDED_FOR_DYNAMIC:
+         add_DT_NEEDED_for_dynamic = TRUE;
          break;
-       case OPTION_NO_ADD_NEEDED:
-         add_needed = FALSE;
+       case OPTION_NO_ADD_DT_NEEDED_FOR_DYNAMIC:
+         add_DT_NEEDED_for_dynamic = FALSE;
          break;
-       case OPTION_AS_NEEDED:
-         as_needed = TRUE;
+       case OPTION_ADD_DT_NEEDED_FOR_REGULAR:
+         add_DT_NEEDED_for_regular = TRUE;
          break;
-       case OPTION_NO_AS_NEEDED:
-         as_needed = FALSE;
+       case OPTION_NO_ADD_DT_NEEDED_FOR_REGULAR:
+         add_DT_NEEDED_for_regular = FALSE;
          break;
        case OPTION_WRAP:
          add_wrap (optarg);
@@ -1389,10 +1447,10 @@ parse_args (unsigned argc, char **argv)
            config.split_by_file = 1;
          break;
        case OPTION_CHECK_SECTIONS:
-         command_line.check_section_addresses = TRUE;
+         command_line.check_section_addresses = 1;
          break;
        case OPTION_NO_CHECK_SECTIONS:
-         command_line.check_section_addresses = FALSE;
+         command_line.check_section_addresses = 0;
          break;
        case OPTION_ACCEPT_UNKNOWN_INPUT_ARCH:
          command_line.accept_unknown_input_arch = TRUE;
@@ -1401,18 +1459,15 @@ parse_args (unsigned argc, char **argv)
          command_line.accept_unknown_input_arch = FALSE;
          break;
        case '(':
-         if (ingroup)
-           einfo (_("%P%F: may not nest groups (--help for usage)\n"));
-
          lang_enter_group ();
-         ingroup = 1;
+         ingroup++;
          break;
        case ')':
          if (! ingroup)
            einfo (_("%P%F: group ended before it began (--help for usage)\n"));
 
          lang_leave_group ();
-         ingroup = 0;
+         ingroup--;
          break;
 
        case OPTION_INIT:
@@ -1443,8 +1498,11 @@ parse_args (unsigned argc, char **argv)
        }
     }
 
-  if (ingroup)
-    lang_leave_group ();
+  while (ingroup)
+    {
+      lang_leave_group ();
+      ingroup--;
+    }
 
   if (default_dirlist != NULL)
     {
@@ -1513,7 +1571,7 @@ set_segment_start (const char *section, char *valstr)
       }
   /* There was no existing value so we must create a new segment
      entry.  */
-  seg = stat_alloc (sizeof (*seg));
+  seg = (segment_type *) stat_alloc (sizeof (*seg));
   seg->name = name;
   seg->value = val;
   seg->used = FALSE;