Jivin Mike Frysinger lays it down ...
> When we converted ld-elf2flt from the shell script to C, one small nuance
> was missed: argv[0] contains the full path only when invoked with the full
> path.  This is not the same behavior for shell scripts as $0 is always the
> full path to the script in question.  Most of the time this isn't an issue
> as gcc will invoke all of its tools (like the linker) with a full relative
> path to itself.  However, if we attempt to invoke the linker directly, we
> can see misbehavior such as:
>       bfin-uclinux-ld.real: cannot open linker script file 
> ./../lib/elf2flt.ld:
>               No such file or directory
> 
> So, to fix this, we lean on more libiberty functions.  Specifically, the
> make_relative_prefix() function.  This function locates a full argv[0] by
> scanning $PATH to see where it was invoked.  This might sound a little
> dodgy, but this is fundamental to how gcc and binutils implement support
> for their runtime relocation, so it can't break ld-elf2flt without first
> breaking every one else ;).
> 
> In the fall out of this fix, we can cull a bunch of local code that does
> custom path parsing.  So not only do we get to fix an annoying bug, we get
> to shrink code in the process.
> 
> Signed-off-by: Steve Kilbane <st...@whitecrow.demon.co.uk>
> Signed-off-by: Mike Frysinger <vap...@gentoo.org>

Applied,

Thanks,
Davidm

> ---
>  ld-elf2flt.c |   76 +++++++++++++++++++++++++++------------------------------
>  1 files changed, 36 insertions(+), 40 deletions(-)
> 
> diff --git a/ld-elf2flt.c b/ld-elf2flt.c
> index 707e9e1..e4cb073 100644
> --- a/ld-elf2flt.c
> +++ b/ld-elf2flt.c
> @@ -46,7 +46,6 @@ static const char *elf2flt = NULL;
>  static const char *nm = NULL;
>  static const char *objdump = NULL;
>  static const char *objcopy = NULL;
> -static const char *tooldir = ".";
>  static const char *ldscriptpath = BINUTILS_LDSCRIPTDIR;
>  
>  /* A list of sed commands */
> @@ -473,47 +472,49 @@ static void parse_args(int argc, char **argv)
>  
>  int main(int argc, char *argv[])
>  {
> -     const char *ptr;
> -     char *tmp;
>       const char *argv0 = argv[0];
> -     size_t len;
> +     const char *argv0_dir = make_relative_prefix(argv0, "/", "/");
> +     char *tooldir = argv0_dir;
> +     char *bindir = argv0_dir;
> +     char *tmp;
>       struct stat buf;
>       const char *have_exe = NULL;
>       int status;
>  
> -     len = strlen(argv0);
>  #ifdef __WIN32
>       /* Remove the .exe extension, if it's there.  */
> +     size_t len = strlen(argv0);
>       if (len > 4 && streq(&argv0[len - 4], ".exe")) {
>               have_exe = ".exe";
>               len -= 4;
>               argv0 = tmp = xstrdup(argv0);
>               tmp[len] = 0;
> +             argv[0][len] = '\0';
>       }
>  #endif
> -     elf2flt_progname = argv0;
> -     for (ptr = elf2flt_progname + len; ptr != elf2flt_progname; ptr--)
> -             if (IS_DIR_SEPARATOR(ptr[-1])) {
> -                     tooldir = tmp = xmalloc(len);
> -                     memcpy(tmp, argv0, len);
> -                     tmp[ptr - elf2flt_progname - 1] = 0;
> -                     elf2flt_progname = ptr;
> -                     /* The standard binutils tool layout has:
> -
> -                        bin/<TARGET_ALIAS>-foo
> -                        lib/
> -                        <TARGET_ALIAS>/bin/foo
> -                        <TARGET_ALIAS>/lib
> -
> -                        It's <TARGET_ALIAS>/ that we want here: files in 
> lib/ are for
> -                        the host while those in <TARGET_ALIAS>/lib are for 
> the target.  */
> -                     if (streqn(elf2flt_progname, TARGET_ALIAS)) {
> -                             tmp = concat(tooldir, "/../" TARGET_ALIAS 
> "/bin", NULL);
> -                             if (stat(tmp, &buf) == 0 && 
> S_ISDIR(buf.st_mode))
> -                                     tooldir = tmp;
> -                     }
> -                     break;
> -             }
> +     elf2flt_progname = lbasename(argv0);
> +
> +     /* The standard binutils tool layout has:
> +
> +        bin/<TARGET_ALIAS>-foo
> +        lib/
> +        <TARGET_ALIAS>/bin/foo
> +        <TARGET_ALIAS>/lib
> +
> +        It's <TARGET_ALIAS>/ that we want here: files in lib/ are for
> +        the host while those in <TARGET_ALIAS>/lib are for the target.
> +        Make bindir point to the bin dir for bin/<TARGET_ALIAS>-foo.
> +        Make tooldir point to the bin dir for <TARGET_ALIAS>/bin/foo.  */
> +     if (streqn(elf2flt_progname, TARGET_ALIAS)) {
> +             tmp = concat(argv0_dir, "../" TARGET_ALIAS "/bin/", NULL);
> +             if (stat(tmp, &buf) == 0 && S_ISDIR(buf.st_mode))
> +                     tooldir = tmp;
> +     } else {
> +             tmp = concat(argv0_dir, "../../bin/", NULL);
> +             if (stat(tmp, &buf) == 0 && S_ISDIR(buf.st_mode))
> +                     bindir = tmp;
> +     }
> +
>       /* Typically ld-elf2flt is invoked as `ld` which means error
>        * messages from it will look like "ld: " which is completely
>        * confusing.  So append an identifier to keep things clear.
> @@ -522,25 +523,20 @@ int main(int argc, char *argv[])
>  
>       xmalloc_set_program_name(elf2flt_progname);
>  
> -     tmp = xmalloc(len + 16);
> -     memcpy(tmp, argv0, len);
> -     while (len && tmp[len - 1] != '-' && !IS_DIR_SEPARATOR(tmp[len - 1]))
> -             len--;
> -     tmp[len] = 0;
> -
> -     linker = concat(tmp, "ld.real", have_exe, NULL);
> -     elf2flt = concat(tmp, "elf2flt", have_exe, NULL);
> -     nm = concat(tmp, "nm", have_exe, NULL);
> -     objdump = concat(tooldir, "/../../bin/", TARGET_ALIAS, "-objdump", 
> have_exe, NULL);
> -     objcopy = concat(tooldir, "/../../bin/", TARGET_ALIAS, "-objcopy", 
> have_exe, NULL);
> +     linker = concat(tooldir, "ld.real", have_exe, NULL);
> +     elf2flt = concat(tooldir, "elf2flt", have_exe, NULL);
> +     nm = concat(tooldir, "nm", have_exe, NULL);
> +     objdump = concat(bindir, TARGET_ALIAS "-objdump", have_exe, NULL);
> +     objcopy = concat(bindir, TARGET_ALIAS "-objcopy", have_exe, NULL);
>  
>       if (stat(ldscriptpath, &buf) || !S_ISDIR(buf.st_mode))
> -             ldscriptpath = concat(tooldir, "/../lib", NULL);
> +             ldscriptpath = concat(tooldir, "../lib", NULL);
>  
>       parse_args(argc, argv);
>  
>       if (flag_verbose) {
>               fprintf(stderr, "argv[0]      = '%s'\n", argv[0]);
> +             fprintf(stderr, "bindir       = '%s'\n", bindir);
>               fprintf(stderr, "tooldir      = '%s'\n", tooldir);
>               fprintf(stderr, "linker       = '%s'\n", linker);
>               fprintf(stderr, "elf2flt      = '%s'\n", elf2flt);
> -- 
> 1.7.2
> 
> _______________________________________________
> uClinux-dev mailing list
> uClinux-dev@uclinux.org
> http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
> This message was resent by uclinux-dev@uclinux.org
> To unsubscribe see:
> http://mailman.uclinux.org/mailman/options/uclinux-dev
> 
> 

-- 
David McCullough,      david_mccullo...@mcafee.com,  Ph:+61 734352815
McAfee - SnapGear      http://www.mcafee.com         http://www.uCdot.org
_______________________________________________
uClinux-dev mailing list
uClinux-dev@uclinux.org
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by uclinux-dev@uclinux.org
To unsubscribe see:
http://mailman.uclinux.org/mailman/options/uclinux-dev

Reply via email to