/* Parse options for the GNU linker.
- Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998
+ Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 1999
Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker.
that might disagree about consts. */
unsigned long strtoul ();
+static int is_num PARAMS ((const char *, int, int, int));
static void set_default_dirlist PARAMS ((char *dirlist_ptr));
static void set_section_start PARAMS ((char *sect, char *valstr));
static void help PARAMS ((void));
#define OPTION_CALL_SHARED (OPTION_ASSERT + 1)
#define OPTION_CREF (OPTION_CALL_SHARED + 1)
#define OPTION_DEFSYM (OPTION_CREF + 1)
-#define OPTION_DYNAMIC_LINKER (OPTION_DEFSYM + 1)
+#define OPTION_DEMANGLE (OPTION_DEFSYM + 1)
+#define OPTION_DYNAMIC_LINKER (OPTION_DEMANGLE + 1)
#define OPTION_EB (OPTION_DYNAMIC_LINKER + 1)
#define OPTION_EL (OPTION_EB + 1)
#define OPTION_EMBEDDED_RELOCS (OPTION_EL + 1)
#define OPTION_HELP (OPTION_EXPORT_DYNAMIC + 1)
#define OPTION_IGNORE (OPTION_HELP + 1)
#define OPTION_MAP (OPTION_IGNORE + 1)
-#define OPTION_NO_KEEP_MEMORY (OPTION_MAP + 1)
+#define OPTION_NO_DEMANGLE (OPTION_MAP + 1)
+#define OPTION_NO_KEEP_MEMORY (OPTION_NO_DEMANGLE + 1)
#define OPTION_NO_WARN_MISMATCH (OPTION_NO_KEEP_MEMORY + 1)
#define OPTION_NOINHIBIT_EXEC (OPTION_NO_WARN_MISMATCH + 1)
#define OPTION_NON_SHARED (OPTION_NOINHIBIT_EXEC + 1)
#define OPTION_VERBOSE (OPTION_UR + 1)
#define OPTION_VERSION (OPTION_VERBOSE + 1)
#define OPTION_VERSION_SCRIPT (OPTION_VERSION + 1)
-#define OPTION_WARN_COMMON (OPTION_VERSION_SCRIPT + 1)
+#define OPTION_VERSION_EXPORTS_SECTION (OPTION_VERSION_SCRIPT + 1)
+#define OPTION_WARN_COMMON (OPTION_VERSION_EXPORTS_SECTION + 1)
#define OPTION_WARN_CONSTRUCTORS (OPTION_WARN_COMMON + 1)
#define OPTION_WARN_MULTIPLE_GP (OPTION_WARN_CONSTRUCTORS + 1)
#define OPTION_WARN_ONCE (OPTION_WARN_MULTIPLE_GP + 1)
#define OPTION_WHOLE_ARCHIVE (OPTION_SPLIT_BY_FILE + 1)
#define OPTION_WRAP (OPTION_WHOLE_ARCHIVE + 1)
#define OPTION_FORCE_EXE_SUFFIX (OPTION_WRAP + 1)
+#define OPTION_GC_SECTIONS (OPTION_FORCE_EXE_SUFFIX + 1)
+#define OPTION_NO_GC_SECTIONS (OPTION_GC_SECTIONS + 1)
+#define OPTION_CHECK_SECTIONS (OPTION_NO_GC_SECTIONS + 1)
+#define OPTION_NO_CHECK_SECTIONS (OPTION_CHECK_SECTIONS + 1)
+#define OPTION_MPC860C0 (OPTION_NO_CHECK_SECTIONS + 1)
+#define OPTION_NO_UNDEFINED (OPTION_MPC860C0 + 1)
+#define OPTION_INIT (OPTION_NO_UNDEFINED + 1)
+#define OPTION_FINI (OPTION_INIT + 1)
/* The long options. This structure is used for both the option
parsing and the help text. */
'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 },
+ { {"EB", no_argument, NULL, OPTION_EB},
+ '\0', NULL, N_("Link big-endian objects"), ONE_DASH },
+ { {"EL", no_argument, NULL, OPTION_EL},
+ '\0', NULL, N_("Link little-endian objects"), ONE_DASH },
{ {"auxiliary", required_argument, NULL, 'f'},
'f', N_("SHLIB"), N_("Auxiliary filter for shared object symbol table"),
TWO_DASHES },
{ {"output", required_argument, NULL, 'o'},
'o', N_("FILE"), N_("Set output file name"), TWO_DASHES },
{ {NULL, required_argument, NULL, '\0'},
- 'O', NULL, N_("Ignored"), ONE_DASH },
+ 'O', NULL, N_("Optimize output file"), ONE_DASH },
+ { {"Qy", no_argument, NULL, OPTION_IGNORE},
+ '\0', NULL, N_("Ignored for SVR4 compatibility"), ONE_DASH },
{ {"relocateable", no_argument, NULL, 'r'},
'r', NULL, N_("Generate relocateable output"), TWO_DASHES },
{ {NULL, no_argument, NULL, '\0'},
'T', N_("FILE"), N_("Read linker script"), TWO_DASHES },
{ {"undefined", required_argument, NULL, 'u'},
'u', N_("SYMBOL"), N_("Start with undefined reference to SYMBOL"), TWO_DASHES },
+ { {"Ur", no_argument, NULL, OPTION_UR},
+ '\0', NULL, N_("Build global constructor/destructor tables"), ONE_DASH },
{ {"version", no_argument, NULL, OPTION_VERSION},
'v', NULL, N_("Print version information"), TWO_DASHES },
{ {NULL, no_argument, NULL, '\0'},
'\0', NULL, NULL, ONE_DASH },
{ {"Bsymbolic", no_argument, NULL, OPTION_SYMBOLIC},
'\0', NULL, N_("Bind global references locally"), ONE_DASH },
+ { {"check-sections", no_argument, NULL, OPTION_CHECK_SECTIONS},
+ '\0', NULL, N_("Check section addresses for overlaps (default)"), TWO_DASHES },
+ { {"no-check-sections", no_argument, NULL, OPTION_NO_CHECK_SECTIONS},
+ '\0', NULL, N_("Do not check section addresses for overlaps"),
+ TWO_DASHES },
{ {"cref", no_argument, NULL, OPTION_CREF},
'\0', NULL, N_("Output cross reference table"), TWO_DASHES },
{ {"defsym", required_argument, NULL, OPTION_DEFSYM},
'\0', N_("SYMBOL=EXPRESSION"), N_("Define a symbol"), TWO_DASHES },
+ { {"demangle", no_argument, NULL, OPTION_DEMANGLE},
+ '\0', NULL, N_("Demangle symbol names"), TWO_DASHES },
{ {"dynamic-linker", required_argument, NULL, OPTION_DYNAMIC_LINKER},
'\0', N_("PROGRAM"), N_("Set the dynamic linker to use"), TWO_DASHES },
- { {"EB", no_argument, NULL, OPTION_EB},
- '\0', NULL, N_("Link big-endian objects"), ONE_DASH },
- { {"EL", no_argument, NULL, OPTION_EL},
- '\0', NULL, N_("Link little-endian objects"), ONE_DASH },
{ {"embedded-relocs", no_argument, NULL, OPTION_EMBEDDED_RELOCS},
'\0', NULL, N_("Generate embedded relocs"), 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},
'\0', NULL, N_("Force generation of file with .exe suffix"), TWO_DASHES},
+ { {"gc-sections", no_argument, NULL, OPTION_GC_SECTIONS},
+ '\0', NULL, N_("Remove unused sections (on some targets)"),
+ TWO_DASHES },
+ { {"no-gc-sections", no_argument, NULL, OPTION_NO_GC_SECTIONS},
+ '\0', NULL, N_("Don't remove unused sections (default)"),
+ TWO_DASHES },
{ {"help", no_argument, NULL, OPTION_HELP},
'\0', NULL, N_("Print option help"), TWO_DASHES },
+ { {"init", required_argument, NULL, OPTION_INIT},
+ '\0', N_("SYMBOL"), N_("Call SYMBOL at load-time"), ONE_DASH },
{ {"Map", required_argument, NULL, OPTION_MAP},
'\0', N_("FILE"), N_("Write a map file"), ONE_DASH },
+ { {"no-demangle", no_argument, NULL, OPTION_NO_DEMANGLE },
+ '\0', NULL, N_("Do not demangle symbol names"), TWO_DASHES },
{ {"no-keep-memory", no_argument, NULL, OPTION_NO_KEEP_MEMORY},
'\0', NULL, N_("Use less memory and more disk I/O"), TWO_DASHES },
+ { {"no-undefined", no_argument, NULL, OPTION_NO_UNDEFINED},
+ '\0', NULL, N_("Allow no undefined symbols"), TWO_DASHES },
{ {"no-warn-mismatch", no_argument, NULL, OPTION_NO_WARN_MISMATCH},
'\0', NULL, N_("Don't warn about mismatched input files"), TWO_DASHES},
{ {"no-whole-archive", no_argument, NULL, OPTION_NO_WHOLE_ARCHIVE},
'\0', N_("TARGET"), N_("Specify target of output file"), TWO_DASHES },
{ {"qmagic", no_argument, NULL, OPTION_IGNORE},
'\0', NULL, N_("Ignored for Linux compatibility"), ONE_DASH },
- { {"Qy", no_argument, NULL, OPTION_IGNORE},
- '\0', NULL, N_("Ignored for SVR4 compatibility"), ONE_DASH },
{ {"relax", no_argument, NULL, OPTION_RELAX},
'\0', NULL, N_("Relax branches on certain targets"), TWO_DASHES },
{ {"retain-symbols-file", required_argument, NULL,
'\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 },
- { {"Ur", no_argument, NULL, OPTION_UR},
- '\0', NULL, N_("Build global constructor/destructor tables"), ONE_DASH },
{ {"verbose", no_argument, NULL, OPTION_VERBOSE},
'\0', NULL, N_("Output lots of information during link"), TWO_DASHES },
{ {"dll-verbose", no_argument, NULL, OPTION_VERBOSE}, /* Linux. */
'\0', NULL, NULL, NO_HELP },
{ {"version-script", required_argument, NULL, OPTION_VERSION_SCRIPT },
'\0', N_("FILE"), N_("Read version information script"), TWO_DASHES },
+ { {"version-exports-section", required_argument, NULL,
+ OPTION_VERSION_EXPORTS_SECTION },
+ '\0', N_("SYMBOL"), N_("Take export symbols list from .exports, using\n\t\t\t\tSYMBOL as the version."),
+ TWO_DASHES },
{ {"warn-common", no_argument, NULL, OPTION_WARN_COMMON},
'\0', NULL, N_("Warn about duplicate common symbols"), TWO_DASHES },
{ {"warn-constructors", no_argument, NULL, OPTION_WARN_CONSTRUCTORS},
{ {"whole-archive", no_argument, NULL, OPTION_WHOLE_ARCHIVE},
'\0', NULL, N_("Include all objects from following archives"), TWO_DASHES },
{ {"wrap", required_argument, NULL, OPTION_WRAP},
- '\0', N_("SYMBOL"), N_("Use wrapper functions for SYMBOL"), TWO_DASHES }
+ '\0', N_("SYMBOL"), N_("Use wrapper functions for SYMBOL"), TWO_DASHES },
+ { {"mpc860c0", optional_argument, NULL, OPTION_MPC860C0},
+ '\0', N_("[=WORDS]"), N_("Modify problematic branches in last WORDS (1-10,\n\t\t\t\tdefault 5) words of a page"), TWO_DASHES }
};
#define OPTION_COUNT ((int) (sizeof ld_options / sizeof ld_options[0]))
+/* Test STRING for containing a string of digits that form a number
+ between MIN and MAX. The return value is the number or ERR. */
+
+static int
+is_num (string, min, max, err)
+ const char *string;
+ int min;
+ int max;
+ int err;
+{
+ int result = 0;
+
+ for (; *string; ++string)
+ {
+ if (! isdigit (*string))
+ {
+ result = err;
+ break;
+ }
+ result = result * 10 + (*string - '0');
+ }
+ if (result < min || result > max)
+ result = err;
+
+ return result;
+}
+
void
parse_args (argc, argv)
int argc;
parsing_defsym = 0;
lex_string = NULL;
break;
+ case OPTION_DEMANGLE:
+ demangling = true;
+ break;
case OPTION_DYNAMIC_LINKER:
command_line.interpreter = optarg;
break;
case 'g':
/* Ignore. */
break;
+ case OPTION_GC_SECTIONS:
+ command_line.gc_sections = true;
+ break;
case OPTION_HELP:
help ();
xexit (0);
config.magic_demand_paged = false;
config.dynamic_link = false;
break;
+ case OPTION_NO_DEMANGLE:
+ demangling = false;
+ break;
+ case OPTION_NO_GC_SECTIONS:
+ command_line.gc_sections = false;
+ break;
case OPTION_NO_KEEP_MEMORY:
link_info.keep_memory = false;
break;
+ case OPTION_NO_UNDEFINED:
+ link_info.no_undefined = true;
+ break;
case OPTION_NO_WARN_MISMATCH:
command_line.warn_mismatch = false;
break;
something, or can we create a new option to do that
(with a syntax similar to -defsym)?
getopt can't handle two args to an option without kludges. */
+
+ /* Enable optimizations of output files. */
+ link_info.optimize = strtoul (optarg, NULL, 0) ? true : false;
break;
case 'o':
lang_add_output (optarg, 0);
command_line.rpath = buystring (optarg);
else
{
+ size_t rpath_len = strlen (command_line.rpath);
+ size_t optarg_len = strlen (optarg);
char *buf;
+ char *cp = command_line.rpath;
- buf = xmalloc (strlen (command_line.rpath)
- + strlen (optarg)
- + 2);
- sprintf (buf, "%s:%s", command_line.rpath, optarg);
- free (command_line.rpath);
- command_line.rpath = buf;
+ /* First see whether OPTARG is already in the path. */
+ do
+ {
+ size_t idx = 0;
+ while (optarg[idx] != '\0' && optarg[idx] == cp[idx])
+ ++idx;
+ if (optarg[idx] == '\0'
+ && (cp[idx] == '\0' || cp[idx] == ':'))
+ /* We found it. */
+ break;
+
+ /* Not yet found. */
+ cp = strchr (cp, ':');
+ if (cp != NULL)
+ ++cp;
+ }
+ while (cp != NULL);
+
+ if (cp == NULL)
+ {
+ buf = xmalloc (rpath_len + optarg_len + 2);
+ sprintf (buf, "%s:%s", command_line.rpath, optarg);
+ free (command_line.rpath);
+ command_line.rpath = buf;
+ }
}
break;
case OPTION_RPATH_LINK:
link_info.strip = strip_all;
break;
case OPTION_SHARED:
- link_info.shared = true;
+ if (config.has_shared)
+ link_info.shared = true;
+ else
+ einfo (_("%P%F: -shared not supported\n"));
break;
case 'h': /* Used on Solaris. */
case OPTION_SONAME:
yyparse ();
}
break;
+ case OPTION_VERSION_EXPORTS_SECTION:
+ /* This option records a version symbol to be applied to the
+ symbols listed for export to be found in the object files
+ .exports sections. */
+ command_line.version_exports_section = optarg;
+ break;
case OPTION_WARN_COMMON:
config.warn_common = true;
break;
case OPTION_SPLIT_BY_FILE:
config.split_by_file = true;
break;
+ case OPTION_CHECK_SECTIONS:
+ command_line.check_section_addresses = true;
+ break;
+ case OPTION_NO_CHECK_SECTIONS:
+ command_line.check_section_addresses = false;
+ break;
case '(':
if (ingroup)
{
lang_leave_group ();
ingroup = 0;
break;
+ case OPTION_MPC860C0:
+ link_info.mpc860c0 = 20; /* default value (in bytes) */
+ if (optarg)
+ {
+ unsigned words;
+ words = is_num (optarg, 1, 10, 0);
+ if (words == 0)
+ {
+ fprintf (stderr,
+ _("%s: Invalid argument to option \"mpc860c0\"\n"),
+ program_name);
+ xexit (1);
+ }
+ link_info.mpc860c0 = words * 4; /* convert words to bytes */
+ }
+ command_line.relax = true;
+ break;
+
+ case OPTION_INIT:
+ link_info.init_function = optarg;
+ break;
+
+ case OPTION_FINI:
+ link_info.fini_function = optarg;
+ break;
}
}
}
}
+ /* Note: Various tools (such as libtool) depend upon the
+ format of the listings below - do not change them. */
/* xgettext:c-format */
printf (_("%s: supported targets:"), program_name);
targets = bfd_target_list ();