[PATCH v3] ld: Use stat to check if linker script appears multiple times

Jan Beulich jbeulich@suse.com
Tue Aug 12 14:16:45 GMT 2025


On 12.08.2025 13:57, H.J. Lu wrote:
> Use stat, instead of strcmp, to check if the same linker script file
> appears multiple times for
> 
> $ ld -L... -T ././/script.t -T script.t ...
> 
> Although ././/script.t and script.t access the same file, but their
> filenames are different.  strcmp won't work here.
> 
> Copy gnulib/import/same-inode.h to include since the gnulib directory
> isn't included in the binutils tarball.
> 
> include/
> 
> 	PR ld/24576
> 	* same-inode.h: New file.  Copied from gnulib/import/same-inode.h.
> 
> ld/
> 
> 	PR ld/24576
> 	* ldfile.c: Include "same-inode.h".
> 	(ldfile_find_command_file): Change the second argument from bool
> 	to enum script_open_style.  Check if the same linker script file
> 	appears multiple times by using stat, instead using strcmp.
> 	(ldfile_open_command_file_1): Don't check if the same linker
> 	script file appears multiple times here.
> 	* testsuite/ld-scripts/pr24576-2.d: New.
> 	* testsuite/ld-scripts/script.exp: Run pr24576-2.
> 
> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>

Looks largely okay to me, but I have one more question and a small remark:

> --- a/ld/ldfile.c
> +++ b/ld/ldfile.c
> @@ -35,6 +35,7 @@
>  #include "libiberty.h"
>  #include "filenames.h"
>  #include <fnmatch.h>
> +#include "same-inode.h"
>  #if BFD_SUPPORTS_PLUGINS
>  #include "plugin.h"
>  #endif /* BFD_SUPPORTS_PLUGINS */
> @@ -828,19 +829,26 @@ find_scripts_dir (void)
>  
>  static FILE *
>  ldfile_find_command_file (const char *name,
> -			  bool default_only,
> +			  enum script_open_style open_how,
>  			  bool *sysrooted)
>  {
>    search_dirs_type *search;
>    FILE *result = NULL;
> -  char *path;
> +  char *path = NULL;
> +  const char *filename = NULL;
> +  struct script_name_list *script;
> +  size_t len;
> +  struct stat sbuf1;
>  
> -  if (!default_only)
> +  if (open_how != script_defaultT)
>      {
>        /* First try raw name.  */
>        result = try_open (name, sysrooted);
>        if (result != NULL)
> -	return result;
> +	{
> +	  filename = name;
> +	  goto success;
> +	}
>      }
>  
>    if (!script_search)
> @@ -861,20 +869,45 @@ ldfile_find_command_file (const char *name,
>    *search_tail_ptr = script_search;
>  
>    /* Try now prefixes.  */
> -  for (search = default_only ? script_search : search_head;
> +  for (search = open_how == script_defaultT ? script_search : search_head;
>         search != NULL;
>         search = search->next)
>      {
>        path = concat (search->name, slash, name, (const char *) NULL);
>        result = try_open (path, sysrooted);
> -      free (path);
>        if (result)
> -	break;
> +	{
> +	  filename = path;
> +	  break;
> +	}
>      }
>  
>    /* Restore the original path list.  */
>    *search_tail_ptr = NULL;
>  
> +success:

May I ask that labels be indented by at least one blank, for the sake of
"diff -p" and alike?

> +  /* PR 24576: Catch the case where the user has accidentally included
> +     the same linker script twice.  */
> +  if (stat (filename, &sbuf1) == 0)
> +    for (script = processed_scripts; script != NULL; script = script->next)
> +      if (open_how != script_nonT || script->open_how != script_nonT)
> +	{
> +	  struct stat sbuf2;
> +	  if (stat (script->name, &sbuf2) == 0
> +	      && SAME_INODE (sbuf1, sbuf2))
> +	    fatal (_("%P: error: linker script file '%s'"
> +		     " appears multiple times\n"), name);

Reporting "name" here may not be very helpful? Imo we want to report both
"filename" and "script->name", which may be entirely different from one
another (and also different from "name").

Jan


More information about the Binutils mailing list