For relative paths in INPUT() and GROUP(), search the directory of the current linker script before searching other paths.

PR ld/25806
	* ldlang.h (struct lang_input_statement_struct): Add extra_search_path.
	* ldlang.c (current_input_file): New.
	(ldirname): New.
	(new_afile): Add from_filename parameter. Set extra_search_path.
	(lang_add_input_file): Pass current_input_file to new_afile.
	(load_symbols): Set current_input_file.
This commit is contained in:
Fangrui Song 2020-04-22 16:20:02 +01:00 committed by Nick Clifton
parent 31c89d6038
commit 161719466a
6 changed files with 77 additions and 12 deletions

View File

@ -1,3 +1,17 @@
2020-04-22 Fangrui Song <maskray@google.com>
PR ld/25806
* ldlang.h (struct lang_input_statement_struct): Add extra_search_path.
* ldlang.c (current_input_file): New.
(ldirname): New.
(new_afile): Add from_filename parameter. Set extra_search_path.
(lang_add_input_file): Pass current_input_file to new_afile.
(load_symbols): Set current_input_file.
* ldfile.c (ldfile_open_file): If extra_search_path has been set
then scan it for the file that needs to be opened.
* ld.texi: Document the new behaviour.
* NEWS: Mention the new feature.
2020-04-22 Alan Modra <amodra@gmail.com>
* testsuite/ld-scripts/default-script1.d: Correct mingw skip.

View File

@ -7,6 +7,10 @@
IMAGIC (0411) for separate instruction and data spaces, and change the
default format option for pdp11-aout to be --omagic.
* Relative pathnames in INPUT() and GROUP() directives in linker scripts are
searched relative to the directory of the linker script before other search
paths.
Changes in 2.34:
* The ld check for "PHDR segment not covered by LOAD segment" is more

View File

@ -3657,13 +3657,16 @@ script, and then invoke the linker with nothing but a @samp{-T} option.
In case a @dfn{sysroot prefix} is configured, and the filename starts
with the @samp{/} character, and the script being processed was
located inside the @dfn{sysroot prefix}, the filename will be looked
for in the @dfn{sysroot prefix}. Otherwise, the linker will try to
open the file in the current directory. If it is not found, the
linker will search through the archive library search path.
The @dfn{sysroot prefix} can also be forced by specifying @code{=}
as the first character in the filename path, or prefixing the filename
path with @code{$SYSROOT}. See also the description of @samp{-L} in
@ref{Options,,Command-line Options}.
for in the @dfn{sysroot prefix}. The @dfn{sysroot prefix} can also be forced by specifying
@code{=} as the first character in the filename path, or prefixing the
filename path with @code{$SYSROOT}. See also the description of
@samp{-L} in @ref{Options,,Command-line Options}.
If a @dfn{sysroot prefix} is not used then the linker will try to open
the file in the directory containing the linker script. If it is not
found the linker will then search the current directory. If it is still
not found the linker will search through the archive library search
path.
If you use @samp{INPUT (-l@var{file})}, @command{ld} will transform the
name to @code{lib@var{file}.a}, as with the command-line argument

View File

@ -416,7 +416,24 @@ ldfile_open_file (lang_input_statement_type *entry)
search_arch_type *arch;
bfd_boolean found = FALSE;
/* Try to open <filename><suffix> or lib<filename><suffix>.a */
/* If extra_search_path is set, entry->filename is a relative path.
Search the directory of the current linker script before searching
other paths. */
if (entry->extra_search_path)
{
char *path = concat (entry->extra_search_path, slash, entry->filename,
(const char *)0);
if (ldfile_try_open_bfd (path, entry))
{
entry->filename = path;
entry->flags.search_dirs = FALSE;
return;
}
free (path);
}
/* Try to open <filename><suffix> or lib<filename><suffix>.a. */
for (arch = search_arch_head; arch != NULL; arch = arch->next)
{
found = ldfile_open_file_search (arch->name, entry, "lib", ".a");

View File

@ -117,6 +117,7 @@ lang_statement_list_type file_chain = { NULL, NULL };
lang_input_statement_type statement (reached via input_statement field in a
lang_statement_union). */
lang_statement_list_type input_file_chain;
static const char *current_input_file;
struct bfd_sym_chain entry_symbol = { NULL, NULL };
const char *entry_section = ".text";
struct lang_input_statement_flags input_flags;
@ -176,6 +177,21 @@ name_match (const char *pattern, const char *name)
return strcmp (pattern, name);
}
static char *
ldirname (const char *name)
{
const char *base = lbasename (name);
char *dirname;
while (base > name && IS_DIR_SEPARATOR (base[-1]))
--base;
if (base == name)
return strdup (".");
dirname = strdup (name);
dirname[base - name] = '\0';
return dirname;
}
/* If PATTERN is of the form archive:file, return a pointer to the
separator. If not, return NULL. */
@ -1093,7 +1109,8 @@ new_statement (enum statement_enum type,
static lang_input_statement_type *
new_afile (const char *name,
lang_input_file_enum_type file_type,
const char *target)
const char *target,
const char *from_filename)
{
lang_input_statement_type *p;
@ -1102,6 +1119,7 @@ new_afile (const char *name,
p = new_stat (lang_input_statement, stat_ptr);
memset (&p->the_bfd, 0,
sizeof (*p) - offsetof (lang_input_statement_type, the_bfd));
p->extra_search_path = NULL;
p->target = target;
p->flags.dynamic = input_flags.dynamic;
p->flags.add_DT_NEEDED_for_dynamic = input_flags.add_DT_NEEDED_for_dynamic;
@ -1142,6 +1160,10 @@ new_afile (const char *name,
case lang_input_file_is_search_file_enum:
p->filename = name;
p->local_sym_name = name;
/* If name is a relative path, search the directory of the current linker
script first. */
if (from_filename && !IS_ABSOLUTE_PATH (name))
p->extra_search_path = ldirname (from_filename);
p->flags.real = TRUE;
p->flags.search_dirs = TRUE;
break;
@ -1181,12 +1203,12 @@ lang_add_input_file (const char *name,
within the sysroot subdirectory.) */
unsigned int outer_sysrooted = input_flags.sysrooted;
input_flags.sysrooted = 0;
ret = new_afile (sysrooted_name, file_type, target);
ret = new_afile (sysrooted_name, file_type, target, NULL);
input_flags.sysrooted = outer_sysrooted;
return ret;
}
return new_afile (name, file_type, target);
return new_afile (name, file_type, target, current_input_file);
}
struct out_section_hash_entry
@ -2909,7 +2931,7 @@ lookup_name (const char *name)
lang_statement_union_type *rest = *after;
stat_ptr->tail = after;
search = new_afile (name, lang_input_file_is_search_file_enum,
default_target);
default_target, NULL);
*stat_ptr->tail = rest;
if (*tail == NULL)
stat_ptr->tail = tail;
@ -3051,7 +3073,9 @@ load_symbols (lang_input_statement_type *entry,
ldfile_assumed_script = TRUE;
parser_input = input_script;
current_input_file = entry->filename;
yyparse ();
current_input_file = NULL;
ldfile_assumed_script = FALSE;
/* missing_file is sticky. sysrooted will already have been

View File

@ -293,6 +293,9 @@ typedef struct lang_input_statement_struct
Usually the same as filename, but for a file spec'd with
-l this is the -l switch itself rather than the filename. */
const char *local_sym_name;
/* Extra search path. Used to find a file relative to the
directory of the current linker script. */
const char *extra_search_path;
bfd *the_bfd;