(main): Look for real-ld' after
gld', before `ld'.
Fix typo in -debug part of previous change. Look for tools using paths rather than a single prefix. (struct prefix_list, struct path_prefix): New structures. (cpath, path): New variables. (find_a_file, add_prefix): New functions; simplified versions of functions from gcc.c. (prefix_from_env): New function. (main): Get path to search for binaries from COMPILER_PATH environment variable always set by gcc.c and from PATH. Qualify names with target machine in cross-environment unless using compiler directories. Use find_a_file to find our binaries. Remove use of single prefix. If -debug, print strip_file_name. (fork_execute): Print program we are trying to execute if -debug and we can't find the file. (scan_prog_file): Complain if can't find nm. From-SVN: r3052
This commit is contained in:
parent
d54d8150fe
commit
bb59f9a64b
426
gcc/collect2.c
426
gcc/collect2.c
@ -73,11 +73,17 @@ extern int errno;
|
||||
|
||||
/* On certain systems, we have code that works by scanning the object file
|
||||
directly. But this code uses system-specific header files and library
|
||||
functions, so turn it off in a cross-compiler. */
|
||||
functions, so turn it off in a cross-compiler. Likewise, the names of
|
||||
the utilities aren't correct for a cross-compiler; we have to hope that
|
||||
cross-versions are in the proper directories. */
|
||||
|
||||
#ifdef CROSS_COMPILE
|
||||
#undef OBJECT_FORMAT_COFF
|
||||
#undef OBJECT_FORMAT_ROSE
|
||||
#undef MD_EXEC_PREFIX
|
||||
#undef REAL_LD_FILE_NAME
|
||||
#undef REAL_NM_FILE_NAME
|
||||
#undef REAL_STRIP_FILE_NAME
|
||||
#endif
|
||||
|
||||
/* If we can't use a special method, use the ordinary one:
|
||||
@ -444,7 +450,169 @@ choose_temp_base ()
|
||||
mktemp (temp_filename);
|
||||
temp_filename_length = strlen (temp_filename);
|
||||
}
|
||||
|
||||
/* By default, colon separates directories in a path. */
|
||||
#ifndef PATH_SEPARATOR
|
||||
#define PATH_SEPARATOR ':'
|
||||
#endif
|
||||
|
||||
/* Structure to hold all the directories in which to search for files to
|
||||
execute. */
|
||||
|
||||
struct prefix_list
|
||||
{
|
||||
char *prefix; /* String to prepend to the path. */
|
||||
struct prefix_list *next; /* Next in linked list. */
|
||||
};
|
||||
|
||||
struct path_prefix
|
||||
{
|
||||
struct prefix_list *plist; /* List of prefixes to try */
|
||||
int max_len; /* Max length of a prefix in PLIST */
|
||||
char *name; /* Name of this list (used in config stuff) */
|
||||
};
|
||||
|
||||
/* We maintain two prefix lists: one from COMPILER_PATH environment variable
|
||||
and one from the PATH variable. */
|
||||
|
||||
static struct path_prefix cpath, path;
|
||||
|
||||
#ifdef CROSS_COMPILE
|
||||
/* This is the name of the target machine. We use it to form the name
|
||||
of the files to execute. */
|
||||
|
||||
static char *target_machine = TARGET_MACHINE;
|
||||
#endif
|
||||
|
||||
/* Search for NAME using prefix list PPREFIX. We only look for executable
|
||||
files.
|
||||
|
||||
Return 0 if not found, otherwise return its name, allocated with malloc. */
|
||||
|
||||
static char *
|
||||
find_a_file (pprefix, name)
|
||||
struct path_prefix *pprefix;
|
||||
char *name;
|
||||
{
|
||||
char *temp;
|
||||
struct prefix_list *pl;
|
||||
int len = pprefix->max_len + strlen (name) + 1;
|
||||
|
||||
#ifdef EXECUTABLE_SUFFIX
|
||||
len += strlen (EXECUTABLE_SUFFIX);
|
||||
#endif
|
||||
|
||||
temp = xmalloc (len);
|
||||
|
||||
/* Determine the filename to execute (special case for absolute paths). */
|
||||
|
||||
if (*name == '/')
|
||||
{
|
||||
if (access (name, X_OK))
|
||||
{
|
||||
strcpy (temp, name);
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
else
|
||||
for (pl = pprefix->plist; pl; pl = pl->next)
|
||||
{
|
||||
strcpy (temp, pl->prefix);
|
||||
strcat (temp, name);
|
||||
if (access (temp, X_OK) == 0)
|
||||
return temp;
|
||||
|
||||
#ifdef EXECUTABLE_SUFFIX
|
||||
/* Some systems have a suffix for executable files.
|
||||
So try appending that. */
|
||||
strcat (temp, EXECUTABLE_SUFFIX);
|
||||
if (access (temp, X_OK) == 0)
|
||||
return temp;
|
||||
#endif
|
||||
}
|
||||
|
||||
free (temp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add an entry for PREFIX to prefix list PPREFIX. */
|
||||
|
||||
static void
|
||||
add_prefix (pprefix, prefix)
|
||||
struct path_prefix *pprefix;
|
||||
char *prefix;
|
||||
{
|
||||
struct prefix_list *pl, **prev;
|
||||
int len;
|
||||
|
||||
if (pprefix->plist)
|
||||
{
|
||||
for (pl = pprefix->plist; pl->next; pl = pl->next)
|
||||
;
|
||||
prev = &pl->next;
|
||||
}
|
||||
else
|
||||
prev = &pprefix->plist;
|
||||
|
||||
/* Keep track of the longest prefix */
|
||||
|
||||
len = strlen (prefix);
|
||||
if (len > pprefix->max_len)
|
||||
pprefix->max_len = len;
|
||||
|
||||
pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
|
||||
pl->prefix = savestring (prefix, len);
|
||||
|
||||
if (*prev)
|
||||
pl->next = *prev;
|
||||
else
|
||||
pl->next = (struct prefix_list *) 0;
|
||||
*prev = pl;
|
||||
}
|
||||
|
||||
/* Take the value of the environment variable ENV, break it into a path, and
|
||||
add of the entries to PPREFIX. */
|
||||
|
||||
static void
|
||||
prefix_from_env (env, pprefix)
|
||||
char *env;
|
||||
struct path_prefix *pprefix;
|
||||
{
|
||||
char *p = getenv (env);
|
||||
|
||||
if (p)
|
||||
{
|
||||
char *startp, *endp;
|
||||
char *nstore = (char *) xmalloc (strlen (p) + 3);
|
||||
|
||||
startp = endp = p;
|
||||
while (1)
|
||||
{
|
||||
if (*endp == PATH_SEPARATOR || *endp == 0)
|
||||
{
|
||||
strncpy (nstore, startp, endp-startp);
|
||||
if (endp == startp)
|
||||
{
|
||||
strcpy (nstore, "./");
|
||||
}
|
||||
else if (endp[-1] != '/')
|
||||
{
|
||||
nstore[endp-startp] = '/';
|
||||
nstore[endp-startp+1] = 0;
|
||||
}
|
||||
else
|
||||
nstore[endp-startp] = 0;
|
||||
|
||||
add_prefix (pprefix, nstore);
|
||||
if (*endp == 0)
|
||||
break;
|
||||
endp = startp = endp + 1;
|
||||
}
|
||||
else
|
||||
endp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Main program. */
|
||||
|
||||
@ -453,13 +621,26 @@ main (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
char *ld_suffix = "ld";
|
||||
char *full_ld_suffix = ld_suffix;
|
||||
char *real_ld_suffix = "real-ld";
|
||||
char *full_real_ld_suffix = ld_suffix;
|
||||
char *gld_suffix = "gld";
|
||||
char *full_gld_suffix = gld_suffix;
|
||||
char *nm_suffix = "nm";
|
||||
char *full_nm_suffix = nm_suffix;
|
||||
char *gnm_suffix = "gnm";
|
||||
char *full_gnm_suffix = gnm_suffix;
|
||||
char *strip_suffix = "strip";
|
||||
char *full_strip_suffix = strip_suffix;
|
||||
char *gstrip_suffix = "gstrip";
|
||||
char *full_gstrip_suffix = gstrip_suffix;
|
||||
char *outfile = "a.out";
|
||||
char *arg;
|
||||
FILE *outf;
|
||||
char *ld_file_name;
|
||||
char *c_file_name;
|
||||
char *p;
|
||||
char *prefix;
|
||||
char **c_argv;
|
||||
char **c_ptr;
|
||||
char **ld1_argv = (char **) xcalloc (sizeof (char *), argc+2);
|
||||
@ -507,148 +688,131 @@ main (argc, argv)
|
||||
if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
|
||||
signal (SIGBUS, handler);
|
||||
|
||||
/* Try to discover a valid linker/assembler/nm/strip to use. */
|
||||
len = strlen (argv[0]);
|
||||
prefix = (char *)0;
|
||||
if (len >= sizeof ("ld")-1)
|
||||
{
|
||||
p = argv[0] + len - sizeof ("ld") + 1;
|
||||
if (strcmp (p, "ld") == 0)
|
||||
{
|
||||
prefix = argv[0];
|
||||
*p = '\0';
|
||||
}
|
||||
}
|
||||
/* Extract COMPILER_PATH and PATH into our prefix list. */
|
||||
prefix_from_env ("COMPILER_PATH", &cpath);
|
||||
prefix_from_env ("PATH", &path);
|
||||
|
||||
if (prefix == (char *)0)
|
||||
{
|
||||
p = rindex (argv[0], '/');
|
||||
if (p != (char *)0)
|
||||
{
|
||||
prefix = argv[0];
|
||||
p[1] = '\0';
|
||||
}
|
||||
#ifdef CROSS_COMPILE
|
||||
/* If we look for a program in the compiler directories, we just use
|
||||
the short name, since these directories are already system-specific.
|
||||
But it we look for a took in the system directories, we need to
|
||||
qualify the program name with the target machine. */
|
||||
|
||||
#ifdef STANDARD_EXEC_PREFIX
|
||||
else if (access (STANDARD_EXEC_PREFIX, X_OK) == 0)
|
||||
prefix = STANDARD_EXEC_PREFIX;
|
||||
#endif
|
||||
full_ld_suffix
|
||||
= xcalloc (strlen (ld_suffix) + strlen (target_machine) + 1, 1);
|
||||
strcpy (full_ld_suffix, ld_suffix);
|
||||
strcat (full_ld_suffix, "-");
|
||||
strcat (full_ld_suffix, target_machine);
|
||||
|
||||
#ifdef MD_EXEC_PREFIX
|
||||
else if (access (MD_EXEC_PREFIX, X_OK) == 0)
|
||||
prefix = MD_EXEC_PREFIX;
|
||||
#endif
|
||||
full_real_ld_suffix
|
||||
= xcalloc (strlen (real_ld_suffix) + strlen (target_machine) + 1, 1);
|
||||
strcpy (full_real_ld_suffix, real_ld_suffix);
|
||||
strcat (full_real_ld_suffix, "-");
|
||||
strcat (full_real_ld_suffix, target_machine);
|
||||
|
||||
else if (access ("/usr/ccs/gcc", X_OK) == 0)
|
||||
prefix = "/usr/ccs/gcc/";
|
||||
full_gld_suffix
|
||||
= xcalloc (strlen (gld_suffix) + strlen (target_machine) + 1, 1);
|
||||
strcpy (full_gld_suffix, gld_suffix);
|
||||
strcat (full_gld_suffix, "-");
|
||||
strcat (full_gld_suffix, target_machine);
|
||||
|
||||
else if (access ("/usr/ccs/bin", X_OK) == 0)
|
||||
prefix = "/usr/ccs/bin/";
|
||||
full_nm_suffix
|
||||
= xcalloc (strlen (nm_suffix) + strlen (target_machine) + 1, 1);
|
||||
strcpy (full_nm_suffix, nm_suffix);
|
||||
strcat (full_nm_suffix, "-");
|
||||
strcat (full_nm_suffix, target_machine);
|
||||
|
||||
else
|
||||
prefix = "/bin/";
|
||||
}
|
||||
full_gnm_suffix
|
||||
= xcalloc (strlen (gnm_suffix) + strlen (target_machine) + 1, 1);
|
||||
strcpy (full_gnm_suffix, gnm_suffix);
|
||||
strcat (full_gnm_suffix, "-");
|
||||
strcat (full_gnm_suffix, target_machine);
|
||||
|
||||
clen = len = strlen (prefix);
|
||||
full_strip_suffix
|
||||
= xcalloc (strlen (strip_suffix) + strlen (target_machine) + 1, 1);
|
||||
strcpy (full_strip_suffix, strip_suffix);
|
||||
strcat (full_strip_suffix, "-");
|
||||
strcat (full_strip_suffix, target_machine);
|
||||
|
||||
#ifdef STANDARD_BIN_PREFIX
|
||||
if (clen < sizeof (STANDARD_BIN_PREFIX) - 1)
|
||||
clen = sizeof (STANDARD_BIN_PREFIX) - 1;
|
||||
#endif
|
||||
full_gstrip_suffix
|
||||
= xcalloc (strlen (gstrip_suffix) + strlen (target_machine) + 1, 1);
|
||||
strcpy (full_gstrip_suffix, gstrip_suffix);
|
||||
strcat (full_gstrip_suffix, "-");
|
||||
strcat (full_gstrip_suffix, target_machine);
|
||||
#endif /* CROSS_COMPILE */
|
||||
|
||||
#ifdef STANDARD_EXEC_PREFIX
|
||||
if (clen < sizeof (STANDARD_EXEC_PREFIX) - 1)
|
||||
clen = sizeof (STANDARD_EXEC_PREFIX) - 1;
|
||||
#endif
|
||||
/* Try to discover a valid linker/nm/strip to use. */
|
||||
|
||||
/* Allocate enough string space for the longest possible pathnames. */
|
||||
ld_file_name = xcalloc (len + sizeof ("real-ld"), 1);
|
||||
nm_file_name = xcalloc (len + sizeof ("gnm"), 1);
|
||||
strip_file_name = xcalloc (len + sizeof ("gstrip"), 1);
|
||||
|
||||
/* Determine the full path name of the ld program to use. */
|
||||
bcopy (prefix, ld_file_name, len);
|
||||
strcpy (ld_file_name + len, "real-ld");
|
||||
if (access (ld_file_name, X_OK) < 0)
|
||||
{
|
||||
strcpy (ld_file_name + len, "gld");
|
||||
if (access (ld_file_name, X_OK) < 0)
|
||||
{
|
||||
free (ld_file_name);
|
||||
/* Search the (target-specific) compiler dirs for `gld'. */
|
||||
ld_file_name = find_a_file (&cpath, gld_suffix);
|
||||
/* Search the ordinary system bin directories
|
||||
for `gld' (if native linking) or `gld-TARGET' (if cross). */
|
||||
if (ld_file_name == 0)
|
||||
ld_file_name = find_a_file (&path, full_gld_suffix);
|
||||
/* Likewise for `real-ld'. */
|
||||
if (ld_file_name == 0)
|
||||
ld_file_name = find_a_file (&cpath, real_ld_suffix);
|
||||
if (ld_file_name == 0)
|
||||
ld_file_name = find_a_file (&path, full_real_ld_suffix);
|
||||
/* Maybe we know the right file to use (if not cross). */
|
||||
#ifdef REAL_LD_FILE_NAME
|
||||
ld_file_name = REAL_LD_FILE_NAME;
|
||||
#else
|
||||
ld_file_name = (access ("/usr/bin/ld", X_OK) == 0
|
||||
? "/usr/bin/ld" : "/bin/ld");
|
||||
if (ld_file_name == 0)
|
||||
ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* This would be the right place to search the compiler dirs
|
||||
for `ld', but we don't do that, since this program is installed
|
||||
there as `ld'. */
|
||||
/* Search the ordinary system bin directories
|
||||
for `ld' (if native linking) or `ld-TARGET' (if cross). */
|
||||
if (ld_file_name == 0)
|
||||
ld_file_name = find_a_file (&path, full_ld_suffix);
|
||||
|
||||
nm_file_name = find_a_file (&cpath, gnm_suffix);
|
||||
if (nm_file_name == 0)
|
||||
nm_file_name = find_a_file (&path, full_gnm_suffix);
|
||||
if (nm_file_name == 0)
|
||||
nm_file_name = find_a_file (&cpath, nm_suffix);
|
||||
#ifdef REAL_NM_FILE_NAME
|
||||
if (nm_file_name == 0)
|
||||
nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME);
|
||||
#endif
|
||||
if (nm_file_name == 0)
|
||||
nm_file_name = find_a_file (&path, full_nm_suffix);
|
||||
|
||||
strip_file_name = find_a_file (&cpath, gstrip_suffix);
|
||||
if (strip_file_name == 0)
|
||||
strip_file_name = find_a_file (&path, full_gstrip_suffix);
|
||||
if (strip_file_name == 0)
|
||||
strip_file_name = find_a_file (&cpath, strip_suffix);
|
||||
#ifdef REAL_STRIP_FILE_NAME
|
||||
if (strip_file_name == 0)
|
||||
strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME);
|
||||
#endif
|
||||
if (strip_file_name == 0)
|
||||
strip_file_name = find_a_file (&path, full_strip_suffix);
|
||||
|
||||
/* Determine the full path name of the C compiler to use. */
|
||||
c_file_name = getenv ("COLLECT_GCC");
|
||||
/* If this is absolute, it must be a file that exists.
|
||||
If it is relative, it must be something that execvp was able to find.
|
||||
Either way, we can pass it to execvp and find the same executable. */
|
||||
if (c_file_name == 0)
|
||||
{
|
||||
c_file_name = xcalloc (clen + sizeof ("gcc"), 1);
|
||||
bcopy (prefix, c_file_name, len);
|
||||
strcpy (c_file_name + len, "gcc");
|
||||
if (access (c_file_name, X_OK) < 0)
|
||||
{
|
||||
#ifdef STANDARD_BIN_PREFIX
|
||||
strcpy (c_file_name, STANDARD_BIN_PREFIX);
|
||||
strcat (c_file_name, "gcc");
|
||||
if (access (c_file_name, X_OK) < 0)
|
||||
#ifdef CROSS_COMPILE
|
||||
c_file_name = xcalloc (strlen ("gcc") + strlen (target_machine) + 1, 1);
|
||||
strcpy (c_file_name, "gcc-");
|
||||
strcat (c_file_name, target_machine);
|
||||
#else
|
||||
c_file_name = "gcc";
|
||||
#endif
|
||||
{
|
||||
#ifdef STANDARD_EXEC_PREFIX
|
||||
strcpy (c_file_name, STANDARD_EXEC_PREFIX);
|
||||
strcat (c_file_name, "gcc");
|
||||
if (access (c_file_name, X_OK) < 0)
|
||||
#endif
|
||||
{
|
||||
strcpy (c_file_name, "gcc");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine the full path name of the nm to use. */
|
||||
bcopy (prefix, nm_file_name, len);
|
||||
strcpy (nm_file_name + len, "nm");
|
||||
if (access (nm_file_name, X_OK) < 0)
|
||||
{
|
||||
strcpy (nm_file_name + len, "gnm");
|
||||
if (access (nm_file_name, X_OK) < 0)
|
||||
{
|
||||
free (nm_file_name);
|
||||
#ifdef REAL_NM_FILE_NAME
|
||||
nm_file_name = REAL_NM_FILE_NAME;
|
||||
#else
|
||||
nm_file_name = (access ("/usr/bin/nm", X_OK) == 0
|
||||
? "/usr/bin/nm" : "/bin/nm");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
p = find_a_file (&cpath, c_file_name);
|
||||
|
||||
/* Determine the full pathname of the strip to use. */
|
||||
bcopy (prefix, strip_file_name, len);
|
||||
strcpy (strip_file_name + len, "strip");
|
||||
if (access (strip_file_name, X_OK) < 0)
|
||||
{
|
||||
strcpy (strip_file_name + len, "gstrip");
|
||||
if (access (strip_file_name, X_OK) < 0)
|
||||
{
|
||||
free (strip_file_name);
|
||||
#ifdef REAL_STRIP_FILE_NAME
|
||||
strip_file_name = REAL_STRIP_FILE_NAME;
|
||||
#else
|
||||
strip_file_name = (access ("/usr/bin/strip", X_OK) == 0
|
||||
? "/usr/bin/strip" : "/bin/strip");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* Here it should be safe to use the system search path since we should have
|
||||
already qualified the name of the compiler when it is needed. */
|
||||
if (p == 0)
|
||||
p = find_a_file (&path, c_file_name);
|
||||
|
||||
if (p)
|
||||
c_file_name = p;
|
||||
|
||||
*ld1++ = *ld2++ = "ld";
|
||||
|
||||
@ -755,10 +919,10 @@ main (argc, argv)
|
||||
if (debug)
|
||||
{
|
||||
char *ptr;
|
||||
fprintf (stderr, "prefix = %s\n", prefix);
|
||||
fprintf (stderr, "ld_file_name = %s\n", ld_file_name);
|
||||
fprintf (stderr, "c_file_name = %s\n", c_file_name);
|
||||
fprintf (stderr, "nm_file_name = %s\n", nm_file_name);
|
||||
fprintf (stderr, "strip_file_name = %s\n", strip_file_name);
|
||||
fprintf (stderr, "c_file = %s\n", c_file);
|
||||
fprintf (stderr, "o_file = %s\n", o_file);
|
||||
|
||||
@ -902,7 +1066,11 @@ fork_execute (prog, argv)
|
||||
char **p_argv;
|
||||
char *str;
|
||||
|
||||
if (prog)
|
||||
fprintf (stderr, "%s", prog);
|
||||
else
|
||||
fprintf (stderr, "[cannot find %s]", argv[0]);
|
||||
|
||||
for (p_argv = &argv[1]; (str = *p_argv) != (char *)0; p_argv++)
|
||||
fprintf (stderr, " %s", str);
|
||||
|
||||
@ -912,6 +1080,12 @@ fork_execute (prog, argv)
|
||||
fflush (stdout);
|
||||
fflush (stderr);
|
||||
|
||||
/* If we can't find a program we need, complain error. Do this here
|
||||
since we might not end up needing something that we couldn't find. */
|
||||
|
||||
if (prog == 0)
|
||||
fatal ("cannot find `%s'", argv[0]);
|
||||
|
||||
pid = vfork ();
|
||||
if (pid == -1)
|
||||
fatal_perror ("vfork");
|
||||
@ -1047,6 +1221,10 @@ scan_prog_file (prog_name, which_pass)
|
||||
if (which_pass != PASS_FIRST)
|
||||
return;
|
||||
|
||||
/* If we don't have an `nm', complain. */
|
||||
if (nm_file_name == 0)
|
||||
fatal ("cannot find `nm'");
|
||||
|
||||
nm_argv[argc++] = "nm";
|
||||
if (NM_FLAGS[0] != '\0')
|
||||
nm_argv[argc++] = NM_FLAGS;
|
||||
|
Loading…
Reference in New Issue
Block a user