On Friday 02 April 2010 18:39:36 Denys Vlasenko wrote:

>      [Requesting program interpreter: /lib/ld-uClibc.so.0]

You'll notice that's a hardwired absolute path.  If you check all the other 
binaries on your system (including the ones your host came with), you'll 
notice they have hardwired absolute paths for this too.

> I can copy or symlink them to ones in cross-compiler-x86_64/lib
> and it will start working.

Unfortunately that's just the way the dynamic linker works.

> But I can't make it for more than one
> cross-compiling toolchain at once, right?

Each dynamic binary needs an absolute path to its dynamic linker.  The kernel 
loads this directly, so it doesn't have a search path, in much the same way 
/sbin/hotplug hasn't got a search path when the kernel launches that.  Such a 
search path wold be putting policy into the kernel.

There's an online book on linking that covers this:

  http://www.iecc.com/linker/linker10.html

> I can use either cross-compiler-i686 or cross-compiler-x86_64,
> but not both at once. But that would be useful.

The wrapper I use is actually run-time configurable with environment variables.

When compiling stuff:

    export CCWRAP_DYNAMIC_LINKER=/lib-uClibc-x86_64/ld-uClibc.so.0

Then copy all the appropraite shared librareis to that directory (or whatever 
name you prefer to use).  The uClibc dynamic linker will look in the directory 
the shared linker is installed in as one of its default locations, see line 
286 of uClibc/ldso/ldso/dl-elf.c:

        /* Look for libraries wherever the shared library loader
         * was installed */
        _dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath);
        if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, 
rpnt)) != NULL)
        {
                return tpnt1;
        }

The downside is of course that it'll fall back to looking in /lib if it 
doesn't find the library it's it's looking for.  The bane of cross compiling is 
falling back to default locations at which the host headers and libraries 
live.  Making it _NOT_ do that is 95% of the game of whack-a-mole you wind up 
playing trying to make this crap work.

But in the case of busybox, that shouldn't be too big an issue.  You don't 
have the "my cross compiler didn't have zlib installed so it found the host 
library" issue because we don't use random external dependencies.  You can't 
leak random external dependencies if you don't _use_ them.

If you did want to hard-wire in both of these changes, you could change the 
default path to the dynamic linker in ccwrap.c on line 197:

http://impactlinux.com/hg/hgwebdir.cgi/firmware/file/f3b242456ff7/sources/toys/ccwrap.c

And then you could fix the dynamic linker library search path fallback problem 
by rebuilding ld-uClibc.so.0 with a different UCLIBC_RUNTIME_PREFIX, although 
if you're going to delve into the horror that is uClibc's path logic, read 
this first:

  http://ibot.rikers.org/%23uclibc/20081210.html.gz

And then probably give up and just hardwire what you want into dl-elf.c line 
299 or so, because it's going to add a hardwired "usr/lib" after the path you 
give it, whether you want it to or not.  (I believe I convinced bernhard to 
stop doing this in current -git, but I haven't gotten around to testing the 
new release candidate yet.)

> For example, in order to run randomconfig tests for both 32
> and 64 bits in parallel overnight.

Build statically and it'll work fine?  That's the easy way...

The thing is, I'm not treating x86 or x86-64 specially.  I'm treating 'em the 
exact same way I treat mips and arm and such.  Those won't run on your host, 
you need to use the emulator to run them.  I go ahead and use the emulator to 
text i486 and such too, because the fact that i486 runs on the host doesn't 
mean it'll run on a real 486, and yes some low-power embedded chips emulate a 
486 but not the pentium instructions:

  http://impactlinux.com/hg/hgwebdir.cgi/firmware/rev/1004

So I generally use a system image, or a chroot with application emulation and 
dynamic linking, or I build statically and use application emulation.

A prominent design goal of these toolchains is to get all the architectures to 
behave as similarly as possible.  Having them use the same dynamic linker name 
is part of that.  When I build an x86-64 image it's fully 64-bit, with no 32 
bit support.  (Same as mips64, or the upcoming ppc64 I'm poking at.)

That's also why they don't multilib: you build with this toolchain, it should 
produce the right output by default.  If you want a different type of output, 
use a different toolchain.  (If I could get one toolchain to support all 
targets, I'd build one and use wrapper scripts to feed in target flags.  But 
gcc wasn't designed with that in mind.  You'll find "gcc wasn't designed with 
that in mind" crops up a LOT when you start playing with it, it's their 
unofficial motto, I think...)

It's not actually that hard to support "32 bit on 64 bit" sort of things.  The 
dynamic linker and default library search path are the main things.  But I'm 
trying to keep down the complexity and having each toolchain and each system 
image support exactly one target is a big part of that.  Not having two 
contentexts that can get confused with each other, thus no cross compiling 
issues.

> I know that various distros use different names, like /lib and /lib64,
> to make it possible. How do they do it?

They hardwire a different path to the dynamic linker into each executable the 
toolchain creates (which in this instance is controlled by ccwrap, see above).  
And then they teach that dynamic linker to look for libraries in /lib64 by 
default, instead of in /lib.  (And then to make themselves feel better they 
move the 32 bit libraries to lib32 and symlink /lib to /lib32, even though 
nothing anywhere ever uses lib32 directly as a path.  Presumably it helps them 
sleep at night to pretend they haven't special-cased 64 bit out the wazoo to 
work around legacy 32 bit binaries.  "See, we abused 32 bit in the same way, 
we just made sure it didn't matter in the slightest by symlinking all the 
paths that are actually _used_ by the legacy binaries we're supporting to 
point to the place we moved it."  Makes me want to pat 'em on the head and go 
"there there, lay on this couch, tell me about your mother"...)

> And do you think it might make sense for you
> to use /lib-$CROSS instead of /lib for every (cross-)compiler,
> making it possible to run many dynamically linked programs
> against different sub-arches on the same machine?

I could, sure.  But you'd still need to use the emulator to run 'em, at which 
point running 'em in a chroot or via a system image makes about as much sense.

> This will be an overkill for the case when one runs just a plain
> one-subarch, but it will still work for that case too, right?

It would work, yes.

Let's talk over the design issues at CELF next week.  If you're serious about 
this use case I can put a config option into my build to automate it for you, 
but I'd like to demonstrate scriptable system images to you first.  I think 
they're a better way to do this sort of thing.

System images are nicely self contained, and don't require root access to run.  
Adding stuff on the host is not self-contained, requires root access, tends to 
bit rot, bypasses your distro's normal package tracking mechanisms (and even 
if it didn't, packages are never tagged as "needed for this project" so 
reproducing the setup on another machine is a pain).  And application emlation 
is inherently more brittle than system emulation anyway so you'll spend lots 
of your time finding bugs in the _emulator_, not in busybox.  (Less so now than 
2 years ago, but still.  In system emulation it generally either works 
completely or not at all, no strange buggy halfway working states.)

Rob
-- 
Latency is more important than throughput. It's that simple. - Linus Torvalds
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to