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