mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-12-15 22:00:47 +08:00
xtensa: add dynconfig option for ld/gas
This needs to build xtensa multilib. Multilib can not operate with
environment variables but with compile options.
bfd/
* bfd/xtensa-dynconfig.c: Add xtensa_dynconfig_file variable.
gas/
* gas/config/tc-xtensa.c: Add dynconfig option.
ld/
* ld/emultempl/xtensaelf.em: Add dynconfig option.
This commit is contained in:
@@ -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,70 @@ 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
|
||||
|
||||
void xtensa_set_dynconfig_from_argv(int argc, char **argv)
|
||||
{
|
||||
const char * const dynconfig_opt = "--dynconfig=";
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (!strncmp (dynconfig_opt, argv[i], strlen(dynconfig_opt)))
|
||||
{
|
||||
xtensa_dynconfig_file = &argv[i][strlen(dynconfig_opt)];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 +140,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 +173,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,12 @@ 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. */
|
||||
xtensa_set_dynconfig_from_argv(argc, argv);
|
||||
|
||||
xg_init_global_config ();
|
||||
}
|
||||
|
||||
|
||||
@@ -129,6 +129,9 @@ extern const struct xtensa_config_v2 *xtensa_get_config_v2 (void);
|
||||
extern const struct xtensa_config_v3 *xtensa_get_config_v3 (void);
|
||||
extern const struct xtensa_config_v4 *xtensa_get_config_v4 (void);
|
||||
|
||||
|
||||
void xtensa_set_dynconfig_from_argv(int argc, char **argv);
|
||||
|
||||
#ifdef XTENSA_CONFIG_DEFINITION
|
||||
|
||||
#ifndef XCHAL_HAVE_MUL32_HIGH
|
||||
|
||||
@@ -61,6 +61,10 @@ static char *
|
||||
elf_xtensa_choose_target (int argc ATTRIBUTE_UNUSED,
|
||||
char **argv ATTRIBUTE_UNUSED)
|
||||
{
|
||||
/* This function is called before LD arguments parsed.
|
||||
* So, dynconfig file must be set first. */
|
||||
xtensa_set_dynconfig_from_argv(argc, argv);
|
||||
|
||||
if (XCHAL_HAVE_BE)
|
||||
return "${BIG_OUTPUT_FORMAT}";
|
||||
else
|
||||
@@ -1931,6 +1935,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='
|
||||
@@ -1941,6 +1946,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='
|
||||
@@ -1959,6 +1966,9 @@ PARSE_AND_LIST_ARGS_CASES='
|
||||
case OPTION_ABI_CALL0:
|
||||
elf32xtensa_abi = XTHAL_ABI_CALL0;
|
||||
break;
|
||||
case OPTION_DYNCONFIG:
|
||||
/* Applied in elf_xtensa_choose_target() */
|
||||
break;
|
||||
'
|
||||
|
||||
# Replace some of the standard ELF functions with our own versions.
|
||||
|
||||
@@ -471,6 +471,7 @@ enum option_values
|
||||
OPTION_NO_LITERAL_MOVEMENT,
|
||||
OPTION_ABI_WINDOWED,
|
||||
OPTION_ABI_CALL0,
|
||||
OPTION_DYNCONFIG,
|
||||
};
|
||||
|
||||
/* The initial parser states. */
|
||||
|
||||
Reference in New Issue
Block a user