@@ -20,6 +20,7 @@
#include "sysdep.h"
#include "bfd.h"
#include "libbfd.h"
+#include "libiberty.h"
#define XTENSA_CONFIG_DEFINITION
#include "xtensa-config.h"
@@ -64,6 +65,57 @@ dlerror (void)
#define CONFIG_ENV_NAME "XTENSA_GNU_CONFIG"
+/* this variable can be changed with input option for gas/ld */
+const char *xtensa_dynconfig_file = "";
+
+#ifdef BFD_SUPPORTS_PLUGINS
+
+static char *get_xtensa_dynconfig_file (void)
+{
+ const char *xtensa_dynconfig_env = getenv (CONFIG_ENV_NAME);
+ if (!strlen (xtensa_dynconfig_file))
+ {
+ if (xtensa_dynconfig_env && !strlen (lbasename (xtensa_dynconfig_env)))
+ {
+ /* XTENSA_GNU_CONFIG has directory path, but dynconfig file is not set */
+ return NULL;
+ }
+ else if (xtensa_dynconfig_env)
+ {
+ /* XTENSA_GNU_CONFIG has filepath */
+ return xstrdup (xtensa_dynconfig_env);
+ }
+ /* dynconfig is not set */
+ return NULL;
+ }
+ if (!xtensa_dynconfig_env)
+ {
+ /* XTENSA_GNU_CONFIG has filepath */
+ return xstrdup (xtensa_dynconfig_file);
+ }
+ if (!strlen (lbasename (xtensa_dynconfig_env)))
+ {
+ /* XTENSA_GNU_CONFIG has directory path and dynconfig file is set */
+ const size_t len = strlen (xtensa_dynconfig_env) +
+ strlen (xtensa_dynconfig_file) + 1;
+ char *path = ( char *) xmalloc (len);
+ strcpy (path, xtensa_dynconfig_env);
+ strcat (path, xtensa_dynconfig_file);
+ return path;
+ }
+ if (strcmp (lbasename (xtensa_dynconfig_env),
+ lbasename (xtensa_dynconfig_file)))
+ {
+ _bfd_error_handler (_("Both %s and \"-dynconfig=\" specified but pointed different files: \"%s\" \"%s\""),
+ CONFIG_ENV_NAME, xtensa_dynconfig_env, xtensa_dynconfig_file);
+ abort ();
+ }
+ /* XTENSA_GNU_CONFIG and mdynconfig option point to the same file */
+ return xstrdup (xtensa_dynconfig_env);
+}
+
+#endif /* BFD_SUPPORTS_PLUGINS */
+
const void *xtensa_load_config (const char *name ATTRIBUTE_UNUSED,
const void *no_plugin_def,
const void *no_name_def ATTRIBUTE_UNUSED)
@@ -75,12 +127,13 @@ const void *xtensa_load_config (const char *name ATTRIBUTE_UNUSED,
if (!init)
{
- const char *path = getenv (CONFIG_ENV_NAME);
+ char *path = get_xtensa_dynconfig_file();
init = 1;
if (!path)
return no_plugin_def;
handle = dlopen (path, RTLD_LAZY);
+ free (path);
if (!handle)
{
_bfd_error_handler (_("%s is defined but could not be loaded: %s"),
@@ -107,7 +160,7 @@ const void *xtensa_load_config (const char *name ATTRIBUTE_UNUSED,
#else
if (!init)
{
- const char *path = getenv (CONFIG_ENV_NAME);
+ const char *path = strcmp(xtensa_dynconfig_file, "") ? xtensa_dynconfig_file : getenv (CONFIG_ENV_NAME);
init = 1;
if (path)
@@ -733,6 +733,8 @@ enum
option_abi_windowed,
option_abi_call0,
+
+ option_dynconfig,
};
const char *md_shortopts = "";
@@ -817,6 +819,7 @@ struct option md_longopts[] =
{ "abi-windowed", no_argument, NULL, option_abi_windowed },
{ "abi-call0", no_argument, NULL, option_abi_call0 },
+ { "dynconfig=", required_argument, NULL, option_dynconfig },
{ NULL, no_argument, NULL, 0 }
};
@@ -1053,6 +1056,12 @@ md_parse_option (int c, const char *arg)
elf32xtensa_abi = XTHAL_ABI_CALL0;
return 1;
+ case option_dynconfig:
+ {
+ /* Applied in xtensa_init() */
+ return 1;
+ }
+
default:
return 0;
}
@@ -1087,7 +1096,9 @@ Xtensa options:\n\
--[no-]separate-prop-tables\n\
[Do not] place Xtensa property records into\n\
individual property sections for each section.\n\
- Default is to generate single property section.\n", stream);
+ Default is to generate single property section.\n\
+ --dynconfig=<file>\n\
+ Use xtensa dynconfig options\n", stream);
}
@@ -5268,8 +5279,22 @@ xg_init_global_config (void)
}
void
-xtensa_init (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
+xtensa_init (int argc, char **argv)
{
+ /* This function is called before AS arguments parsed.
+ * So, dynconfig file must be set first.
+ */
+ int i;
+ const char * const dynconfig_opt = "--dynconfig=";
+ for (i = 1; i < argc; i++)
+ {
+ if (!strncmp (dynconfig_opt, argv[i], strlen(dynconfig_opt)))
+ {
+ extern const char* xtensa_dynconfig_file;
+ xtensa_dynconfig_file = &argv[i][strlen(dynconfig_opt)];
+ break;
+ }
+ }
xg_init_global_config ();
}
@@ -1930,6 +1930,7 @@ PARSE_AND_LIST_PROLOGUE='
#define OPTION_NO_LITERAL_MOVEMENT (OPTION_LITERAL_MOVEMENT + 1)
#define OPTION_ABI_WINDOWED (OPTION_NO_LITERAL_MOVEMENT + 1)
#define OPTION_ABI_CALL0 (OPTION_ABI_WINDOWED + 1)
+#define OPTION_DYNCONFIG (OPTION_ABI_CALL0 + 1)
extern int elf32xtensa_size_opt;
extern int elf32xtensa_no_literal_movement;
extern int elf32xtensa_abi;
@@ -1941,6 +1942,7 @@ PARSE_AND_LIST_LONGOPTS='
{ "no-literal-movement", no_argument, NULL, OPTION_NO_LITERAL_MOVEMENT},
{ "abi-windowed", no_argument, NULL, OPTION_ABI_WINDOWED},
{ "abi-call0", no_argument, NULL, OPTION_ABI_CALL0},
+ { "dynconfig=", required_argument, NULL, OPTION_DYNCONFIG},
'
PARSE_AND_LIST_OPTIONS='
@@ -1951,6 +1953,8 @@ PARSE_AND_LIST_OPTIONS='
--abi-windowed Choose windowed ABI for the output object\n"));
fprintf (file, _("\
--abi-call0 Choose call0 ABI for the output object\n"));
+ fprintf (file, _("\
+ --dynconfig=FILE Choose xtensa dynconfig file\n"));
'
PARSE_AND_LIST_ARGS_CASES='
@@ -1969,6 +1973,12 @@ PARSE_AND_LIST_ARGS_CASES='
case OPTION_ABI_CALL0:
elf32xtensa_abi = XTHAL_ABI_CALL0;
break;
+ case OPTION_DYNCONFIG:
+ {
+ extern const char* xtensa_dynconfig_file;
+ xtensa_dynconfig_file = optarg;
+ break;
+ }
'
# Replace some of the standard ELF functions with our own versions.