public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] ld: Find files relative to the current linker script for INPUT() and GROUP()
@ 2020-04-20  6:07 Fangrui Song
  2020-04-20 10:45 ` Nick Clifton
  0 siblings, 1 reply; 6+ messages in thread
From: Fangrui Song @ 2020-04-20  6:07 UTC (permalink / raw)
  To: binutils; +Cc: Fangrui Song

For relative paths in INPUT() and GROUP(), search the directory of the
current linker script before searching other paths.  This feature makes
it feasible to use relative paths in a linker script to refer to files
not in a library path, e.g.

  GROUP(libm-3.a libmvec.a)

or

  INPUT(libc++.a.1 libc++abi.a)

Note, extra_search_path does not apply to -l

	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.
---
 ld/ChangeLog | 10 ++++++++++
 ld/ldfile.c  | 14 ++++++++++++++
 ld/ldlang.c  | 30 ++++++++++++++++++++++++++----
 ld/ldlang.h  |  3 +++
 4 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/ld/ChangeLog b/ld/ChangeLog
index dffd363494..d03acbbc28 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,13 @@
+2020-04-20  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.
+
 2020-04-20  Alan Modra  <amodra@gmail.com>
 
 	* testsuite/ld-powerpc/tlsopt5.s: Rename foo to aaaaa.
diff --git a/ld/ldfile.c b/ld/ldfile.c
index d98429d7b8..2e877d5584 100644
--- a/ld/ldfile.c
+++ b/ld/ldfile.c
@@ -416,6 +416,20 @@ ldfile_open_file (lang_input_statement_type *entry)
       search_arch_type *arch;
       bfd_boolean found = FALSE;
 
+      /* If extra_search_path is set, entry->filename is a relative path.
+         Search the directory of the current linkerscript 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;
+          }
+        }
+
       /* Try to open <filename><suffix> or lib<filename><suffix>.a */
       for (arch = search_arch_head; arch != NULL; arch = arch->next)
 	{
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 0bb5f3c044..f1fc7900f2 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -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,19 @@ name_match (const char *pattern, const char *name)
   return strcmp (pattern, name);
 }
 
+static char *
+ldirname (const char *name)
+{
+  const char *base = lbasename (name);
+  while (base > name && IS_DIR_SEPARATOR (base[-1]))
+    --base;
+  if (base == name)
+    return strdup (".");
+  char *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 +1107,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 +1117,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 +1158,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 +1201,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 +2929,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 +3071,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
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 8dd4bfda19..8152659faf 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -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;
 
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] ld: Find files relative to the current linker script for INPUT() and GROUP()
  2020-04-20  6:07 [PATCH] ld: Find files relative to the current linker script for INPUT() and GROUP() Fangrui Song
@ 2020-04-20 10:45 ` Nick Clifton
  2020-04-20 11:53   ` Alan Modra
  2020-04-20 22:54   ` [PATCH v2] " Fangrui Song
  0 siblings, 2 replies; 6+ messages in thread
From: Nick Clifton @ 2020-04-20 10:45 UTC (permalink / raw)
  To: Fangrui Song, binutils

Hi Fangrui,

> 	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.

Note - adding a new feature like this definitely needs some documentation
added to ld/ld.texi, an entry in ld/NEWS and ideally one or more new tests
added to ld/testsuite/ld-scripts.


> diff --git a/ld/ChangeLog b/ld/ChangeLog
> index dffd363494..d03acbbc28 100644

FYI - there is no need to include the ChangeLog as part of the context
diff.  Providing it as plain text, as you have done above, is sufficient.
Indeed having a diff to a changelog entry often makes the patch fail to
apply cleanly as the changelogs do get updated quite often.


> +      /* If extra_search_path is set, entry->filename is a relative path.
> +         Search the directory of the current linkerscript script before
> +         searching other paths. */

s/linkerscript/linker script/


> +      if (entry->extra_search_path)
> +        {
> +          char *path = concat (entry->extra_search_path, slash, entry->filename,
> +                               (const char *)0);

I prefer NULL to (const char *)0 myself.


> +          if (ldfile_try_open_bfd (path, entry)) {

Formatting: Please put the { on a separate line.


> +            entry->filename = path;
> +            entry->flags.search_dirs = FALSE;
> +            return;
> +          }There is a memory leak here - path is not freed.
> +        }



>  	 within the sysroot subdirectory.)  */
>        unsigned int outer_sysrooted = input_flags.sysrooted;
>        input_flags.sysrooted = 0;

This code fragment made me wonder.  Have you tested your patch
in a sys-rooted environment ?  Does it still work ?

Plus that reminds me - which target(s) have you used to check this patch ?

Cheers
  Nick


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] ld: Find files relative to the current linker script for INPUT() and GROUP()
  2020-04-20 10:45 ` Nick Clifton
@ 2020-04-20 11:53   ` Alan Modra
  2020-04-20 11:54     ` Nick Clifton
  2020-04-20 22:54   ` [PATCH v2] " Fangrui Song
  1 sibling, 1 reply; 6+ messages in thread
From: Alan Modra @ 2020-04-20 11:53 UTC (permalink / raw)
  To: Nick Clifton; +Cc: Fangrui Song, binutils

On Mon, Apr 20, 2020 at 11:45:49AM +0100, Nick Clifton via Binutils wrote:
> > +          char *path = concat (entry->extra_search_path, slash, entry->filename,
> > +                               (const char *)0);
> 
> I prefer NULL to (const char *)0 myself.

Bad idea in this particular case (an ellipsis arg).  The C89 standard
allows NULL to be defined as 0.  See 6.4.2.3 point 3.  An int might
not be the same size as a const char *.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] ld: Find files relative to the current linker script for INPUT() and GROUP()
  2020-04-20 11:53   ` Alan Modra
@ 2020-04-20 11:54     ` Nick Clifton
  0 siblings, 0 replies; 6+ messages in thread
From: Nick Clifton @ 2020-04-20 11:54 UTC (permalink / raw)
  To: Alan Modra; +Cc: Fangrui Song, binutils

Hi Alan,

> On Mon, Apr 20, 2020 at 11:45:49AM +0100, Nick Clifton via Binutils wrote:
>>> +          char *path = concat (entry->extra_search_path, slash, entry->filename,
>>> +                               (const char *)0);
>>
>> I prefer NULL to (const char *)0 myself.
> 
> Bad idea in this particular case (an ellipsis arg).  The C89 standard
> allows NULL to be defined as 0.  See 6.4.2.3 point 3.  An int might
> not be the same size as a const char *.

Did not know that.  Thanks for the heads-up. :-)

Cheers
  Nick


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2] ld: Find files relative to the current linker script for INPUT() and GROUP()
  2020-04-20 10:45 ` Nick Clifton
  2020-04-20 11:53   ` Alan Modra
@ 2020-04-20 22:54   ` Fangrui Song
  2020-04-22 15:41     ` Nick Clifton
  1 sibling, 1 reply; 6+ messages in thread
From: Fangrui Song @ 2020-04-20 22:54 UTC (permalink / raw)
  To: Nick Clifton; +Cc: binutils

[-- Attachment #1: Type: text/plain, Size: 5349 bytes --]

On 2020-04-20, Nick Clifton wrote:
>Hi Fangrui,
>
>> 	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.
>
>Note - adding a new feature like this definitely needs some documentation
>added to ld/ld.texi, an entry in ld/NEWS

Added some contents to ld/ld.texi and ld/NEWS in PATCH v2.

> and ideally one or more new tests>added to ld/testsuite/ld-scripts.

....... it is unfortunate that I cannot find *ANY* test related to
INPUT/GROUP search rules (ld/testsuite/ld-{i386,x86-64}/pr24276.dso have the
substring "INPUT(" but they are not related to search rules)

I do have some personal tests, but I don't know how to place them within the current testing framework (ld/testsuite/ld-elf/* if I understand correctly)

Scroll down to the bottom to see my tests.

>> diff --git a/ld/ChangeLog b/ld/ChangeLog
>> index dffd363494..d03acbbc28 100644
>
>FYI - there is no need to include the ChangeLog as part of the context
>diff.  Providing it as plain text, as you have done above, is sufficient.
>Indeed having a diff to a changelog entry often makes the patch fail to
>apply cleanly as the changelogs do get updated quite often.

Ack. Dropped ld/ChangeLog in PATCH v2.

>> +      /* If extra_search_path is set, entry->filename is a relative path.
>> +         Search the directory of the current linkerscript script before
>> +         searching other paths. */
>
>s/linkerscript/linker script/

Fixed.

>> +      if (entry->extra_search_path)
>> +        {
>> +          char *path = concat (entry->extra_search_path, slash, entry->filename,
>> +                               (const char *)0);
>
>I prefer NULL to (const char *)0 myself.

If I interpret Alan's comment correctly, I will keep (const char *)0 as is.

>
>> +          if (ldfile_try_open_bfd (path, entry)) {
>
>Formatting: Please put the { on a separate line.

Fixed.

>> +            entry->filename = path;
>> +            entry->flags.search_dirs = FALSE;
>> +            return;
>> +          }There is a memory leak here - path is not freed.
>> +        }

Added `free (path) to the else branch.  I don't know how to address the then
branch. Near line 100, we have such code:

   if (name[0] == '=')
     new_dirs->name = concat (ld_sysroot, name + 1, (const char *) NULL);
   else if (CONST_STRNEQ (name, "$SYSROOT"))
     new_dirs->name = concat (ld_sysroot, name + strlen ("$SYSROOT"), (const char *) NULL);
   else
     new_dirs->name = xstrdup (name);

I follow suit and assign an allocated string to extra_search_path.

>
>
>>  	 within the sysroot subdirectory.)  */
>>        unsigned int outer_sysrooted = input_flags.sysrooted;
>>        input_flags.sysrooted = 0;
>
>This code fragment made me wonder.  Have you tested your patch
>in a sys-rooted environment ?  Does it still work ?
>
>Plus that reminds me - which target(s) have you used to check this patch ?

>Cheers
>  Nick

Linux x86-64. The tests I want to use are something like the following,
a free-form shell style testing.

# REQUIRES: x86
## For a relative pathname in INPUT() or GROUP(), the parent directory of
## the current linker script has priority over current working directory and -L.

# RUN: rm -rf %t.dir && mkdir %t.dir && cd %t.dir

# RUN: mkdir dir
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o a.o
# RUN: echo '.globl b, cwd; b: cwd:' | llvm-mc -filetype=obj -triple=x86_64 - -o b.o
# RUN: echo '.globl b, dir; b: dir:' | llvm-mc -filetype=obj -triple=x86_64 - -o dir/b.o
# RUN: ar rc libb.a b.o
# RUN: ar rc dir/libb.a dir/b.o

## A relative pathname is relative to the parent directory of the current linker script.
## The directory has priority over current working directory and -L.
# RUN: echo 'INPUT(libb.a)' > dir/relative.lds
# RUN: ld-new -L. a.o dir/relative.lds -o relative
# RUN: nm relative | FileCheck --check-prefix=DIR %s
## GROUP() uses the same search order.
# RUN: echo 'GROUP(libb.a)' > dir/relative1.lds
# RUN: ld-new -L. a.o dir/relative1.lds -o relative1
# RUN: nm relative1 | FileCheck --check-prefix=DIR %s

# DIR: T dir

## -l does not use the special rule.
# RUN: echo 'INPUT(-lb)' > dir/cwd.lds
# RUN: ld-new -L. a.o dir/cwd.lds -o cwd
# RUN: nm cwd | FileCheck --check-prefix=CWD %s
# RUN: echo 'GROUP(-lb)' > dir/cwd1.lds
# RUN: ld-new -L. a.o dir/cwd1.lds -o cwd1
# RUN: nm cwd1 | FileCheck --check-prefix=CWD %s

# CWD: T cwd

## If the parent directory of the current linker script does not contain the file,
## fall back to the current working directory.
# RUN: cp libb.a libc.a
# RUN: echo 'INPUT(libc.a)' > dir/fallback.lds
# RUN: ld-new a.o dir/fallback.lds -o /dev/null

.globl _start
_start:
   call b

# The above is adapted from https://reviews.llvm.org/D77779?id=258631


The main components of the testing framework are

* a tool to invoke RUN lines as shell commands
* a meta grep (FileCheck) which checks whether its stdin contains certain input lines with flexible patterns
   (https://llvm.org/docs/CommandGuide/FileCheck.html)


This is actually somethine I wanted to propose on this list :) We need
to reimplement the meta grep tool and the testing framework.

[-- Attachment #2: 0001-ld-Find-files-relative-to-the-current-linker-script-.patch --]
[-- Type: text/x-diff, Size: 7913 bytes --]

From 19795819d37737996ad924fd06306624b2234afc Mon Sep 17 00:00:00 2001
From: Fangrui Song <maskray@google.com>
Date: Sun, 19 Apr 2020 21:49:12 -0700
Subject: [PATCH v2] ld: Find files relative to the current linker script for
 INPUT() and GROUP()

For relative paths in INPUT() and GROUP(), search the directory of the
current linker script before searching other paths.  This feature makes
it feasible to use relative paths in a linker script to refer to files
not in a library path, e.g.

  GROUP(libm-3.a libmvec.a)

or

  INPUT(libc++.a.1 libc++abi.a)

Note, extra_search_path does not apply to -l

	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.
---
 ld/NEWS     |  3 +++
 ld/ld.texi  | 13 +++++++------
 ld/ldfile.c | 17 +++++++++++++++++
 ld/ldlang.c | 30 ++++++++++++++++++++++++++----
 ld/ldlang.h |  3 +++
 5 files changed, 56 insertions(+), 10 deletions(-)

diff --git a/ld/NEWS b/ld/NEWS
index 9795b58a5f..e10b58e7ec 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -7,6 +7,9 @@
   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() are searched relative to the
+  directory of the current linker script before other search paths.
+
 Changes in 2.34:
 
 * The ld check for "PHDR segment not covered by LOAD segment" is more
diff --git a/ld/ld.texi b/ld/ld.texi
index 8286af65ee..3cef1b30b4 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -3658,12 +3658,13 @@ 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}.
+open the file in the directory of the current linker script. If it is
+not found, the linker will search the current directory. If it is
+still 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}.
 
 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
diff --git a/ld/ldfile.c b/ld/ldfile.c
index d98429d7b8..ef4ef14d27 100644
--- a/ld/ldfile.c
+++ b/ld/ldfile.c
@@ -416,6 +416,23 @@ ldfile_open_file (lang_input_statement_type *entry)
       search_arch_type *arch;
       bfd_boolean found = FALSE;
 
+      /* 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;
+            }
+	  else
+	    free (path);
+        }
+
       /* Try to open <filename><suffix> or lib<filename><suffix>.a */
       for (arch = search_arch_head; arch != NULL; arch = arch->next)
 	{
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 0bb5f3c044..f1fc7900f2 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -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,19 @@ name_match (const char *pattern, const char *name)
   return strcmp (pattern, name);
 }
 
+static char *
+ldirname (const char *name)
+{
+  const char *base = lbasename (name);
+  while (base > name && IS_DIR_SEPARATOR (base[-1]))
+    --base;
+  if (base == name)
+    return strdup (".");
+  char *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 +1107,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 +1117,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 +1158,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 +1201,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 +2929,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 +3071,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
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 8dd4bfda19..8152659faf 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -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;
 
-- 
2.26.1.301.g55bc3eb7cb9-goog


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] ld: Find files relative to the current linker script for INPUT() and GROUP()
  2020-04-20 22:54   ` [PATCH v2] " Fangrui Song
@ 2020-04-22 15:41     ` Nick Clifton
  0 siblings, 0 replies; 6+ messages in thread
From: Nick Clifton @ 2020-04-22 15:41 UTC (permalink / raw)
  To: Fangrui Song; +Cc: binutils

Hi Fangrui,

  Thanks - I have applied your v2 patch.

> # RUN: rm -rf %t.dir && mkdir %t.dir && cd %t.dir
> [...]

It sounds like the run_ld_link_tests proc will do most of
what you need.  (See ld/testsuite/lib/ld-lib.exp).  Something like:

  run_ld_link_tests [list \
    [list "Build libb.a" "rc" "" "" {b1.s b2.s} {} "tmpdir/libb.a"] \
    [list "Link with script in TMPDIR that INPUTS libb.a", "-T tmpdir/script.t" "" "" {a.s} {} "test.exe"] \
  ]

I have not actually tested this, but I think that it shows what might work.
Take a look in ld/testsuite/ld-x86_64/x86_64.exp for examples of using
run_ld_link_tests to build libraries and then test them.

You might also need to use "exec cp ..." to copy the linker script into
the temporary directory.  See ld/testsuite/ld-elfvers/vers.exp for an
example of copying a file.

Cheers
  Nick



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-04-22 15:41 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-20  6:07 [PATCH] ld: Find files relative to the current linker script for INPUT() and GROUP() Fangrui Song
2020-04-20 10:45 ` Nick Clifton
2020-04-20 11:53   ` Alan Modra
2020-04-20 11:54     ` Nick Clifton
2020-04-20 22:54   ` [PATCH v2] " Fangrui Song
2020-04-22 15:41     ` Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).