[uClinux-dev] [PATCH] ld-elf2flt.c: fix runtime relocatable support
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 --- 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[])
Re: [uClinux-dev] [PATCH] ld-elf2flt.c: fix runtime relocatable support
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
Re: [uClinux-dev] [PATCH] ld-elf2flt.c: fix runtime relocatable support
On Tue, Aug 17, 2010 at 12:26 AM, David McCullough wrote: Applied, damn; your new mcafee overlords making you fast or something ? :) -mike ___ 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
Re: [uClinux-dev] [PATCH] ld-elf2flt.c: fix runtime relocatable support
Jivin Mike Frysinger lays it down ... On Tue, Aug 17, 2010 at 12:26 AM, David McCullough wrote: Applied, damn; your new mcafee overlords making you fast or something ? :) Oops, sorry about that ;-) -- 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