mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 12:34:43 +00:00
ld: Use stat to check if linker script appears multiple times
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-1.d: Adjusted. * 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>
This commit is contained in:
47
include/same-inode.h
Normal file
47
include/same-inode.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/* Determine whether two stat buffers are known to refer to the same file.
|
||||||
|
|
||||||
|
Copyright (C) 2006, 2009-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This file is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef SAME_INODE_H
|
||||||
|
# define SAME_INODE_H 1
|
||||||
|
|
||||||
|
# include <sys/types.h>
|
||||||
|
|
||||||
|
# if defined __VMS && __CRTL_VER < 80200000
|
||||||
|
# define SAME_INODE(a, b) \
|
||||||
|
((a).st_ino[0] == (b).st_ino[0] \
|
||||||
|
&& (a).st_ino[1] == (b).st_ino[1] \
|
||||||
|
&& (a).st_ino[2] == (b).st_ino[2] \
|
||||||
|
&& (a).st_dev == (b).st_dev)
|
||||||
|
# elif defined _WIN32 && ! defined __CYGWIN__
|
||||||
|
/* Native Windows. */
|
||||||
|
# if _GL_WINDOWS_STAT_INODES
|
||||||
|
/* stat() and fstat() set st_dev and st_ino to 0 if information about
|
||||||
|
the inode is not available. */
|
||||||
|
# define SAME_INODE(a, b) \
|
||||||
|
(!((a).st_ino == 0 && (a).st_dev == 0) \
|
||||||
|
&& (a).st_ino == (b).st_ino && (a).st_dev == (b).st_dev)
|
||||||
|
# else
|
||||||
|
/* stat() and fstat() set st_ino to 0 always. */
|
||||||
|
# define SAME_INODE(a, b) 0
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# define SAME_INODE(a, b) \
|
||||||
|
((a).st_ino == (b).st_ino \
|
||||||
|
&& (a).st_dev == (b).st_dev)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif
|
||||||
74
ld/ldfile.c
74
ld/ldfile.c
@@ -35,6 +35,7 @@
|
|||||||
#include "libiberty.h"
|
#include "libiberty.h"
|
||||||
#include "filenames.h"
|
#include "filenames.h"
|
||||||
#include <fnmatch.h>
|
#include <fnmatch.h>
|
||||||
|
#include "same-inode.h"
|
||||||
#if BFD_SUPPORTS_PLUGINS
|
#if BFD_SUPPORTS_PLUGINS
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#endif /* BFD_SUPPORTS_PLUGINS */
|
#endif /* BFD_SUPPORTS_PLUGINS */
|
||||||
@@ -828,19 +829,26 @@ find_scripts_dir (void)
|
|||||||
|
|
||||||
static FILE *
|
static FILE *
|
||||||
ldfile_find_command_file (const char *name,
|
ldfile_find_command_file (const char *name,
|
||||||
bool default_only,
|
enum script_open_style open_how,
|
||||||
bool *sysrooted)
|
bool *sysrooted)
|
||||||
{
|
{
|
||||||
search_dirs_type *search;
|
search_dirs_type *search;
|
||||||
FILE *result = NULL;
|
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. */
|
/* First try raw name. */
|
||||||
result = try_open (name, sysrooted);
|
result = try_open (name, sysrooted);
|
||||||
if (result != NULL)
|
if (result != NULL)
|
||||||
return result;
|
{
|
||||||
|
filename = name;
|
||||||
|
goto success;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!script_search)
|
if (!script_search)
|
||||||
@@ -861,20 +869,47 @@ ldfile_find_command_file (const char *name,
|
|||||||
*search_tail_ptr = script_search;
|
*search_tail_ptr = script_search;
|
||||||
|
|
||||||
/* Try now prefixes. */
|
/* Try now prefixes. */
|
||||||
for (search = default_only ? script_search : search_head;
|
for (search = open_how == script_defaultT ? script_search : search_head;
|
||||||
search != NULL;
|
search != NULL;
|
||||||
search = search->next)
|
search = search->next)
|
||||||
{
|
{
|
||||||
path = concat (search->name, slash, name, (const char *) NULL);
|
path = concat (search->name, slash, name, (const char *) NULL);
|
||||||
result = try_open (path, sysrooted);
|
result = try_open (path, sysrooted);
|
||||||
free (path);
|
|
||||||
if (result)
|
if (result)
|
||||||
break;
|
{
|
||||||
|
filename = path;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore the original path list. */
|
/* Restore the original path list. */
|
||||||
*search_tail_ptr = NULL;
|
*search_tail_ptr = NULL;
|
||||||
|
|
||||||
|
success:
|
||||||
|
/* PR 24576: Catch the case where the user has accidentally included
|
||||||
|
the same linker script twice. */
|
||||||
|
if (stat (filename, &sbuf1) == 0)
|
||||||
|
{
|
||||||
|
struct stat sbuf2;
|
||||||
|
for (script = processed_scripts;
|
||||||
|
script != NULL;
|
||||||
|
script = script->next)
|
||||||
|
if ((open_how != script_nonT || script->open_how != script_nonT)
|
||||||
|
&& stat (script->name, &sbuf2) == 0
|
||||||
|
&& SAME_INODE (sbuf1, sbuf2))
|
||||||
|
fatal (_("%P: error: linker script file '%s (%s)'"
|
||||||
|
" appears multiple times\n"), filename, script->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen (filename);
|
||||||
|
script = xmalloc (sizeof (*script) + len);
|
||||||
|
script->next = processed_scripts;
|
||||||
|
script->open_how = open_how;
|
||||||
|
memcpy (script->name, filename, len + 1);
|
||||||
|
processed_scripts = script;
|
||||||
|
|
||||||
|
free (path);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -886,31 +921,8 @@ ldfile_open_command_file_1 (const char *name, enum script_open_style open_how)
|
|||||||
{
|
{
|
||||||
FILE *ldlex_input_stack;
|
FILE *ldlex_input_stack;
|
||||||
bool sysrooted;
|
bool sysrooted;
|
||||||
struct script_name_list *script;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
/* PR 24576: Catch the case where the user has accidentally included
|
ldlex_input_stack = ldfile_find_command_file (name, open_how,
|
||||||
the same linker script twice. */
|
|
||||||
for (script = processed_scripts; script != NULL; script = script->next)
|
|
||||||
{
|
|
||||||
if ((open_how != script_nonT || script->open_how != script_nonT)
|
|
||||||
&& strcmp (name, script->name) == 0)
|
|
||||||
{
|
|
||||||
fatal (_("%P: error: linker script file '%s'"
|
|
||||||
" appears multiple times\n"), name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
len = strlen (name);
|
|
||||||
script = xmalloc (sizeof (*script) + len);
|
|
||||||
script->next = processed_scripts;
|
|
||||||
script->open_how = open_how;
|
|
||||||
memcpy (script->name, name, len + 1);
|
|
||||||
processed_scripts = script;
|
|
||||||
|
|
||||||
ldlex_input_stack = ldfile_find_command_file (name,
|
|
||||||
open_how == script_defaultT,
|
|
||||||
&sysrooted);
|
&sysrooted);
|
||||||
if (ldlex_input_stack == NULL)
|
if (ldlex_input_stack == NULL)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
#source: default-script.s
|
#source: default-script.s
|
||||||
#ld: -defsym _START=0x800 -T default-script.t -T default-script.t
|
#ld: -defsym _START=0x800 -T default-script.t -T default-script.t
|
||||||
#error: .*default-script.t' appears multiple times
|
#error: .*default-script.t\)' appears multiple times
|
||||||
|
|||||||
3
ld/testsuite/ld-scripts/pr24576-2.d
Normal file
3
ld/testsuite/ld-scripts/pr24576-2.d
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#source: default-script.s
|
||||||
|
#ld: -defsym _START=0x800 -T ././/default-script.t -T default-script.t
|
||||||
|
#error: .*default-script.t\)' appears multiple times
|
||||||
@@ -234,6 +234,7 @@ run_dump_test "output-section-types"
|
|||||||
run_dump_test "ld-version"
|
run_dump_test "ld-version"
|
||||||
run_dump_test "ld-version-2"
|
run_dump_test "ld-version-2"
|
||||||
run_dump_test "pr24576-1"
|
run_dump_test "pr24576-1"
|
||||||
|
run_dump_test "pr24576-2"
|
||||||
|
|
||||||
run_dump_test "segment-start" {{name (default)}}
|
run_dump_test "segment-start" {{name (default)}}
|
||||||
run_dump_test "segment-start" {{name (overridden)} \
|
run_dump_test "segment-start" {{name (overridden)} \
|
||||||
|
|||||||
Reference in New Issue
Block a user