len = strlen (name);
while (1)
{
+ unsigned offset = 0;
char * var;
char *filename, *sset;
/* PR 20535: Support the same pseudo-environment variables that
are supported by ld.so. Namely, $ORIGIN, $LIB and $PLATFORM.
Since there can be more than one occurrence of these tokens in
- the path we loop until no more are found. */
- while ((var = strchr (filename, '$')) != NULL)
+ the path we loop until no more are found. Since we might not
+ be able to substitute some of the tokens we maintain an offset
+ into the filename for where we should begin our scan. */
+ while ((var = strchr (filename + offset, '$')) != NULL)
{
/* The ld.so manual page does not say, but I am going to assume that
these tokens are terminated by a directory seperator character
$ORIGIN should only be used at the start of a path, but that is
not enforced here.
- FIXME: The ld.so manual page also states that it allows ${ORIGIN}
- ${LIB} and ${PLATFORM}. We should support these variants too.
+ The ld.so manual page also states that it allows ${ORIGIN},
+ ${LIB} and ${PLATFORM}, so these are supported as well.
FIXME: The code could be a lot cleverer about allocating space
for the processed string. */
char * end = strchr (var, '/');
char * replacement = NULL;
+ char * v = var + 1;
char * freeme = NULL;
unsigned flen = strlen (filename);
/* Temporarily terminate the filename at the end of the token. */
* end = 0;
- switch (var[1])
+ if (*v == '{')
+ ++ v;
+ switch (*v++)
{
case 'O':
- if (strcmp (var + 2, "RIGIN") == 0)
+ if (strcmp (v, "RIGIN") == 0 || strcmp (v, "RIGIN}") == 0)
{
/* ORIGIN - replace with the full path to the directory
containing the program or shared object. */
if (needed.by == NULL)
- break;
- replacement = bfd_get_filename (needed.by);
+ {
+ if (link_info.output_bfd == NULL)
+ {
+ break;
+ }
+ else
+ replacement = bfd_get_filename (link_info.output_bfd);
+ }
+ else
+ replacement = bfd_get_filename (needed.by);
+
if (replacement)
{
char * slash;
break;
case 'L':
- if (strcmp (var + 2, "IB") == 0)
+ if (strcmp (v, "IB") == 0 || strcmp (v, "IB}") == 0)
{
/* LIB - replace with "lib" in 32-bit environments
and "lib64" in 64-bit environments. */
break;
case 'P':
- if (strcmp (var + 2, "LATFORM") == 0)
- {
- /* Supporting $PLATFORM in a cross-hosted environment is not
- possible. Supporting it in a native environment involves
- loading the <sys/auxv.h> header file which loads the
- system <elf.h> header file, which conflicts with the
- "include/elf/mips.h" header file. */
- replacement = NULL;
- }
- break;
-
+ /* Supporting $PLATFORM in a cross-hosted environment is not
+ possible. Supporting it in a native environment involves
+ loading the <sys/auxv.h> header file which loads the
+ system <elf.h> header file, which conflicts with the
+ "include/elf/mips.h" header file. */
+ /* Fall through. */
default:
break;
}
char * filename2 = xmalloc (flen + strlen (replacement));
if (end)
- sprintf (filename2, "%.*s%s/%s",
- (int)(var - filename), filename,
- replacement, end + 1);
+ {
+ sprintf (filename2, "%.*s%s/%s",
+ (int)(var - filename), filename,
+ replacement, end + 1);
+ offset = (var - filename) + 1 + strlen (replacement);
+ }
else
- sprintf (filename2, "%.*s%s",
- (int)(var - filename), filename,
- replacement);
-
+ {
+ sprintf (filename2, "%.*s%s",
+ (int)(var - filename), filename,
+ replacement);
+ offset = var - filename + strlen (replacement);
+ }
+
free (filename);
filename = filename2;
/* There is no need to restore the path separator (when
if (end)
/* Restore the path separator. */
* end = '/';
+
+ /* PR 20784: Make sure that we resume the scan
+ *after* the token that we could not replace. */
+ offset = (var + 1) - filename;
}
free (freeme);
}
needed.name = filename;
+
if (gld${EMULATION_NAME}_try_needed (&needed, force))
return TRUE;