[uClinux-dev] [PATCH] ld-elf2flt.c: fix runtime relocatable support

2010-08-16 Thread Mike Frysinger
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

2010-08-16 Thread David McCullough

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

2010-08-16 Thread Mike Frysinger
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

2010-08-16 Thread David McCullough

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