[Toybox] Implementing ldd.

enh enh at google.com
Mon Jan 24 14:52:43 PST 2022


On Fri, Jan 21, 2022 at 7:22 PM Rob Landley <rob at landley.net> wrote:
>
> On 1/20/22 2:41 PM, enh wrote:
> > (sorry for the delay; specifically because there's a ton of weird
> > stuff behind the scenes, it took me a while to find the time to write
> > a reply. and even this is just an overview!)
>
> Yesterday's trivial bugfix was my first commit to toybox in 10 days. Not gonna
> throw stones.
>
> Speaking of, Pascal's Apology incoming...
>
> > On Fri, Jan 14, 2022 at 9:07 PM Rob Landley <rob at landley.net> wrote:
> >>
> >> On 1/13/22 1:20 PM, enh wrote:
> >> > TL;DR: unless you're writing your own dynamic linker, i'm not sure why
> >> > you'd write an ldd?
> >>
> >> Well to start with uClibc had a standalone one back in the day:
> >>
> >>   https://git.busybox.net/uClibc/tree/utils/ldd.c
> >>
> >> Which is basically a subset of readelf, and we have readelf...
> >>
> >> The one built into glibc can't tell you anything about a musl or bionic binary
> >> let alone something cross-compiled for another architecture.
> >
> > yeah, "i want to check my Android libraries on the host" is the use
> > case we always hear. unfortunately, "i think you'll find it's a bit
> > more complicated than that"...
>
> You maintain a C library. The only person I've met who _might_ know more about
> this than you is Rich Felker. I certainly am not even close.
>
> That said, I used the old uClibc one and it was better than not having it. Your
> objection seems to be to calling it ldd?

yeah, pretty much. if i had a better suggestion i'd have made it.
"neededs" seems both easy to remember and unlikely to ever be wanted
by anything else (as opposed to, say, "needs")?

> Busybox had a "strings" that was profoundly crappier than the binutils one, and
> I'm poking at an ar.c implementation that doesn't do the gnu hash thingy because
> I can't find documentation for it and am not reading GPLv3 source code to learn
> how to write non-GPLv3 source code, on general principles. I'm aware that a
> toybox tool may be missing features other tools have, but it's designed to let
> you mix and match with other implementations. (Even my tar pipes data through
> external process pulled out of the $PATH when it doesn't have to, because
> modular interoperability.)
>
> I'm aware that musl has an ldd and when you're in a dynamic musl system that's
> what you want to use. But when you're _not_ in a dynamic musl system (chroot,
> static install where /lib isn't there) running ldd against a binary to figure
> out what dependencies it has is nice. You can get the data from readelf, or
> objdump, or file could be extended to show it (it shows dynamic linker already),
> but ldd is the usual way to do that.

i think that's my fundamental disagreement. readelf/objdump is the
normal way to list DT_NEEDEDs.  ldd is a much more specific question,
and you *need* to basically be the linker to answer that question. the
man page for ldd agrees with me.

> > in particular, these are some of the most common Android issues (none
> > of which even the *real* ldd handles --- they ask for "ldd on the
> > host", but that's never what they actually mean):
>
> I want "ldd on the host" to mean what users need it to mean.
>
> How is "there are things even the existing ldd doesn't handle" a good argument
> against toybox ldd existing?
>
> > * did you copy all your libraries into your apk?
> > * did you put all your libraries in the right *directory* in the apk?
> > * did you make sure they're the right *architecture* (and that they're
> > in the right subdirectory for that architecture)?
>
> Not sure this is ldd's job, but... An apk is still basically a zip file, right?
>
> I have a design todo to figure out how "zless" and friends should work (a name
> being a trivial pipeline, but possibly internal to a single process), and "get
> files from zip/tar/fat/isofs instead of filesystem" is kinda one of those.
>
> Assuming I work out a way to do it, being able to point ldd at an apk and a
> chroot from the host isn't _that_ infeasible. (Not the first drop, either...)
>
> > * are the SONAMEs correct? (in particular: not Windows \\ paths (!))
>
> Why does a soname have a path in it? (The dynamic linker is a different record
> type...)
>
> Throwing a warning for "colon before first slash" and "wrong-way-backslash"
> seems reasonable. That said, what you're describing is a sanitizer script that
> _uses_ ldd or readelf or something. Not ldd.

indeed, but when people don't want *real* ldd (which you're not even
thinking about building), what they're asking [me] for is *this*, not
"recursive DT_NEEDEDs". (the confusion comes because they often say
"how do i get recursive DT_NEEDEDs?" because they don't even *know*
there's all this other stuff... and they're disappointed when they get
their recursive DT_NEEDEDs that it wasn't what they wanted after all.)

> > * have you tested on older Android versions where resolution differs?
>
> sanitizer --apk=blah --root=/different/root/filesystem
>
> In theory I could have a function iterate through a directory of apk files and
> treat it as a virtual filesystem. If that Google recruiter DID come up with a
> job working on AOSP or the NDK or something I'd have a good excuse to learn more
> about this stuff, but we spoke over two weeks ago and I haven't heard back since...
>
> I'm currently coming up to speed on how to build an ASIC toolchain using qflow
> and greywolf and qrouter and so on, and then feeding the result into magic and
> spice (or maybe xyce) for testing. Not really leaving a whole lot of bandwidth
> for going through Khem Raj's old ELC tutorials about the early stages of android
> system installation...
>
> Anyway, horrible black magic heuristics for version skew gotchas sound like they
> belong in a magic apk than rather than hardwired as magic rules into the tool,
> but either way the tool probably wouldn't be ldd?
>
> > * okay, so they're the right arch and in the right directory, and the
> > SONAME is fine --- but you do know you can't just copy a glibc binary
> > from your host and drop it in your apk, right?
>
> In theory the dynamic linker name should reveal that one?

(the people who ask for "recursive DT_NEEDEDs" aren't sophisticated
enough for that kind of thing. if they were, they wouldn't be asking
these questions in the first place, or copying host .so files into
.apks and fundamentally failing to understand why that doesn't just
work...)

> In 2010 I did a 6 month contract at Qualcomm helping them port Linux to Hexagon,
> and part of that involved dismantling the uclibc dynamic linker and making
> dynamic linking actually WORK on that architecture. (They'd got static linking
> working, but I was cross compiling x11 clients to it for a demo so we could run
> xeyes and xchess and stuff on comet boards, exported through the network to
> another machine with a display of course, and unfortunately x11 last statically
> compiled during the Clinton administration and no matter what order you put the
> libraries in they leaked unresolved references...)
>
> I made it work. I had to understand REL vs RELA and all sorts of stuff I've
> since forgotten, but I still have Lavine's little "linkers and loaders" book and
> I'm the one who poked refspecs.linuxfoundation.org to actually host the darn
> arch specs (because they didn't at the time). This isn't inherently more
> horrific than strace,

(it is though. the linux kernel *tries* not to break its ABI, and the
linux kernel *mostly* doesn't change its behavior wildly based on
runtime configuration and who the caller is. plus: if you have a
dynamic linker, you have an ldd. if you have a kernel, you still don't
have an strace. [if you actually care about uclibc, which you say has
an unfinished dynamic linker, fixing that uclibc bug probably makes
more sense!])

> and I _do_ note I've intended to do a qcc forever that
> would multiplex cc/ld/as/strip/nm/readelf/objdump/ar/cpp/strings/make. (Which
> kind of implies moving some of the toybox commands over to a new infrstructure,
> possibly the same main.c and lib with a different toys directory? Haven't had
> bandwidth to poke at that forever, but my old notes are at:
>
> https://landley.net/code/qcc
> http://landley.net/hg/qcc/file/tip/todo/todo.txt
> http://landley.net/hg/qcc/file/tip/todo/commands.txt
> http://elinux.org/CELF_Project_Proposal/Combine_tcg_with_tcc
>
> I'm not intimidated by the complexity of "doing it right",

("complexity" isn't really the point so much as "uselessness"... to
give the same answers as ldd, you need to duplicate large chunks of
Android, and parse a bunch of on-device configuration so it doesn't
work on the host anyway.)

> but so far this month
> I've been too busy with other things to even work on command editing+history for
> toysh...
>
> That said, "here are the libraries" and "you have android API version skew"
> still seem like different questions. "What libraries does this binary ask for"
> and "does this binary fit into its filesystem" are different questions.

(exactly. lld is the latter. "recursive DT_NEEDEDs" is the former.
please don't pollute the existing name :-) )

> >> I can never remember if it's "readelf -a" or "readelf -A" to fetch it with the
> >> more complex tool, and it's way harder to script something like
> >> https://git.busybox.net/busybox/tree/testsuite/testing.sh#n111 with readelf's
> >> output.
> >>
> >> "What libraries does this command fail if it can't load" seems a fairly
> >> straightforward question to ask? Usually I'm trying to figure out what
> >> dependencies to transplant when ripping binaries out of a system. (Disrto skew,
> >> version skew, hacking together an initramfs on a USB stick...)
> >
> > aye, but that's just `readelf -dW | grep NEEDED`. and the nice thing
> > about that is that its limitations are nice and clear. ldd is a bit
> > magic, and your "readelf ldd" would have none of that magic. (let
> > alone cover the stuff that even ldd doesn't.)
> >
> > [funnily enough, i see man7's ldd page basically suggests the same if
> > you want to look at an untrusted binary, but uses `objdump -p | grep
> > NEEDED` instead.]
>
> As a bug workaround to the gnu/dammit ldd being horribly insecure, yes:
>
>    Security
>        Be aware that in some circumstances (e.g., where the program  specifies
>        an  ELF  interpreter  other than ld-linux.so), some versions of ldd may
>        attempt to obtain the dependency information by attempting to  directly
>        execute  the  program, which may lead to the execution of whatever code
>        is defined in the program's ELF interpreter, and perhaps  to  execution
>        of  the  program  itself.  (In glibc versions before 2.27, the upstream
>        ldd implementation did this for example,  although  most  distributions
>        provided a modified version that did not.)
>
>        Thus,  you  should  never  employ ldd on an untrusted executable, since
>        this may result in the execution of arbitrary code.  A  safer  alterna‐
>        tive when dealing with untrusted executables is:
>
>            $ objdump -p /path/to/program | grep NEEDED
>
>        Note, however, that this alternative shows only the direct dependencies
>        of the executable, while ldd shows the entire dependency  tree  of  the
>        executable.
>
> I could see having a wrapper script for recursively finding dependencies (and in
> fact _made_ such a wrapper script that found the dependencies of loaded
> libraries back in that busybox test script I pointed at earlier, because back
> then ldd wasn't doing it). But toybox doesn't ship wrapper scripts. There was
> some early flirtation with that back near the start of the archive...
>
> Heh, I forgot that commit 5257cf54a581 has no parent. (Fixed up by 1f24e8080858,
> it was because I did a commit as root which left some of the files under .hg
> unwriteable to my normal user and mercurial didn't have its error checking right
> so the result was a successful but parentless commit. I break everything.
> Someday, github or similar will probably throw a fit about that out of the blue...)
>
> Anyway, I tried some wrappers in commit 5b67c38f8631 and started converting them
> to proper commands in 32e3dccc892c. (I'm sure I explained it somewhere but...
> the mailing list archive has no posts that week, not my blog, not release notes,
> not twitter... Then again my blog entry from that time
> (https://landley.net/notes-2012.html#03-08-2012) kinda explains why. (Death
> march at work and sandwiched between an SF convention and a linux convention on
> the bracketing weekends.)
>
> ANYWAY, the logic was "toybox is a single file which (when statically linked)
> has no dependencies". It may reach out and read files like /etc/usb.ids but that
> triggers extra functionality and it generally shouldn't even complain if they're
> not there. (Of course to do its job it may need files in /proc and /etc/passwd
> and such, but that's operating system API, not stuff installed just for toybox.)
>
> >> > personally i don't think a readelf-based ldd makes much sense? there
> >> > are a ton of weird special cases that mean you really do need the
> >> > "suck it and see" implementation
> >>
> >> Such as?
> >
> > a few examples of stuff [that happens all the time] that ldd *does*
> > catch that "readelf ldd" wouldn't:
> > * symbols that don't resolve.
>
> Technically, ldd doesn't require the library to exist? I'm not trying to solve
> the halting problem here. Where's my neverwinter nights install...

(i said symbols, not libraries. again: people *say* "recursive
DT_NEEDEDs", but that's rarely their problem/never their only problem.
almost every .so has a DT_NEEDED for libc, but did you set things up
right so your code will run on *this* version of libc?)

> $ ldd nwmain
>         linux-gate.so.1 (0xf7fd0000)
>         libm.so.6 => /lib32/libm.so.6 (0xf7edc000)
>         libpthread.so.0 => /lib32/libpthread.so.0 (0xf7ebb000)
>         libGL.so.1 => not found
>         libGLU.so.1 => not found
>         libmss.so.6 => not found
>         libSDL-1.2.so.0 => not found
>         libc.so.6 => /lib32/libc.so.6 (0xf7cdd000)
>         /lib/ld-linux.so.2 (0xf7fd2000)
>
> That install is circa 2003, built for something like red hat 6 I think? Last I
> checked I can still run it with an LD_PRELOAD wrapper script that points it at
> multiple .so files harvested from old systems. Guess how I put that together?
>
> > * DT_NEEDEDs on libraries that you're not allowed to access (a
> > run-time decision based on linker namespaces on Android).
> > * incorrect ELF notes for stuff like PAC/BTI.
>
> Still sounding like a verifier, not ldd.
>
> > * what library your DT_NEEDED *actually* resolves to (which even on
> > glibc involves parsing text files, no? and i don't know how glibc's
> > new per-arch variant optimized builds stuff works, but that's probably
> > something ldd does know).
>
> I'm aware of build time linker script text files (and had to teach tinycc about
> their existence back in the day), but I hadn't encountered dynamic linker
> scripts? There's LD_PATH and LD_PRELOAD and friends, and the horror that is
> ldconfig. But again: falling back to dlopen() and letting the static one "not
> found" for everything seems a reasonable behavior to me?
>
> >> > --- bionic already just has a
> >> > one-line shell script that passes an argument to the dynamic linker
> >> > (and i think glibc and musl work this way too).
> >>
> >> Musl points an "ldd" symlink at the dynamic linker which notices the argv[0]
> >> name and behaves differently. (I may have made puppy eyes at Rich years ago, I'd
> >> have to check my back email...)
> >
> > yeah, that's exactly what we do too :-)
> >
> > tbh, i think it's the only option that makes sense: "hey, linker, do
> > you stuff, just don't actually run the code when you're finished".
>
> Which is of course why the gnu ldd is a shell script complicated enough I've
> been using it to test toysh (which says #!/bin/bash at the start and thus pulls
> in bash as a _runtime_ dependency of glibc) and they trigger the LDD behavior by
> listening to an environment variable (LD_TRACE_LOADED_OBJECTS) that you can
> easily cripple things by setting...
>
> Not a high bar for doing better than if you ask me...
>
> >> The script you mention does not appear to be shipped in the NDK:
> >>
> >>   $ find android-ndk-r24-beta1 -name '*ldd*'
> >>   $
> >
> > no, because like i keep saying --- ldd doesn't really make sense as a
> > host tool :-)
>
> The uclibc guys thought it did.

(other than you mentioning them as your usual example of broken stuff,
i've literally never heard of them. i'm guessing they're an obsolete
ancestor of newlib/picolibc? not the best recommendation :-) )

> > check out /system/bin/ldd instead.
> >
> > (or keep grepping readelf/objdump if *that's* all you want instead!)
>
> man ldd:
>
>   ldd prints the shared objects (shared libraries) required by each pro‐
>   gram or shared object specified on the command line.
>
> >> Or aosp prebuilts:
> >>
> >>   $ find aosp -name '*ldd'
> >>   aosp/external/ltp/testcases/commands/ldd
> >>   $
> >>
> >> But then it doesn't seem to be installed in the cross compilers musl-cross-make
> >> builds either. That said, I can symlink it myself:
> >>
> >> $ cd x86_64-linux-musl-cross
> >> $ ln -s x86_64-linux-musl/lib/libc.so ldd
> >>
> >> If I point yours at an sh4 binary linked against musl will it work?
> >
> > no, because that's not the question ldd answers :-) see above.
>
> It's the question the uclibc ldd answered, once upon a time...
>
> I could theoretically extend "file" to answer it, but ldd is the conventional
> tool that asked this question.
>
> >> Because the
> >> musl one won't:
> >>
> >> $ ./ldd ../sh2eb-linux-muslfdpic-cross/sh2eb-linux-muslfdpic/lib/libc.so
> >> ./ldd: ../sh2eb-linux-muslfdpic-cross/sh2eb-linux-muslfdpic/lib/libc.so: Not a
> >> valid dynamic program
> >> $ echo 'main() {;}' |
> >> ../sh2eb-linux-muslfdpic-cross/bin/sh2eb-linux-muslfdpic-cc -x c -
> >> $ ./ldd a.out
> >> ./ldd: a.out: Not a valid dynamic program
> >
> > that seems like the correct answer to the question *ldd* answers,
>
> "prints the shared objects (shared libraries) required by each program or shared
> object specified on the command line."
>
> > in
> > the same way that Android's ldd can only tell you "will this work on
> > *this* device?". sure, x86-64 Android apps are a thing, but they may
> > well not run on your device.
>
> I keep being surprised when non-x86 binaries run on my laptop because devuan set
> up the binfmt_misc plumbing pointed at qemu application support.
>
> Of couse that only works for statically linked binaries because the library
> search path is wrong otherwise. (I don't have uClibc and bionic installed under
> /. In theory I could do so with bionic since /system doesn't exist on
> conventional Linux, but it's the same "I use my phone as a phone" thing. Petri
> dishes do not go in the food fridge. No mad science in the living room.)
>
> > furthermore, because the usual app
> > System.loadLibrary() environment is different from the [less
> > restricted] adb shell environment, /system/bin/ldd doesn't really
> > answer the question for an *app* anyway. you can quite easily have
> > something that works fine from `adb shell` but not from an app. (aka
> > "my unit test works but my app doesn't".)
>
> "Will it run" and "what libraries does it require" still seem like two different
> questions. Something I can't currently run can require a known set of libraries.
>
> > to answer the *app* question, you need your CI to actually start your
> > app on an actual device/emulator.
>
> Yeah, glibc went down the garden path of "let's run the program and then ask it
> what it loaded", which is not something libc5 was ever crazy enough to do, and
> it turned out to be a security problem. That always struck me as a gnu problem.
>
> You're currently saying there are a lot of things that even bionic's ldd can't
> reliably tell people (such as you're currently running it in a different
> permissions context than you plan to deploy it in), and that's the reason not to
> implement a simple ldd in toybox.
>
> >> But the old uClibc ldd from the dawn of time?
> >>
> >> $ wget -O-
> >> https://landley.net/aboriginal/downloads/old/binaries/1.4.0/cross-compiler-x86_64.tar.gz
> >> | tar xvz
> >> $ cross-compiler-x86_64/bin/x86_64-ldd a.out
> >>         libc.so => not found (0x00000000)
> >>         not a dynamic executable
> >>
> >> Well it's a little unhappy (doesn't know about fdpic for one thing), but it did
> >> tell me what shared library the file needed. Alas, it doesn't seem to recognize
> >> the ndk toolchain's output at all, probably sanity checking header flags and new
> >> ones have been added since...)
> >>
> >> > which isn't to say that the question doesn't sometimes come up of "i'd
> >> > like to print the transitive closure of DT_NEEDEDs *on the host*" but
> >> > note that that's *not* the same thing, and so even if someone does
> >> > write that, it probably deserves a different tool name and a big "note
> >> > that your run-time mileage may vary wildly".
> >>
> >> The ldd in uClibc showed the DT_NEEDED entries in an ELF file, and at the time
> >> that's basically what glibc's did too (just... badly). I used it for ~10 years
> >> and don't remember hitting one of the corner cases you're mentioning? (I'm
> >> guessing a C++ name demangling thing?)
> >
> > yeah, the only time i use ldd on the *host* is indeed for "list the
> > transitive DT_NEEDEDs, please". but even there, i'm often specifically
> > interested in "which exact version of libfoo, and from which
> > directory". and only the real linker can give me the real answer.
>
> Does that mean a "file" command that can't identify all types of file wasn't
> worth implementing?
>
> You're coming up with questions the tool can't answer and using that to argue
> against toybox having the tool. Many of these are questions existing version of
> the tool can't answer either.

(no, not really ... i'm saying something more like "look, real people
are already confused enough, and i think this idea would *increase*
rather than *decrease* confusion". like we agreed at the top, i think
as long as this is called something that makes it clear what it
*actually* is, it's not completely useless. though the few people who
genuinely *only* need "recursive DT_NEEDEDs" and know that are also
fully capable of writing the script themselves if/when they need it, i
think. as always, i'm not too worried about them. i'm worried about
the folks who have no idea what they're doing, and how we make sure
they don't get even more misled.)

> > i guess for me the question of whether your "fakedd" is ever going to
> > find itself on a system where you don't have the real thing?
>
> Well right now I don't have any ldd in the ndk and if I want to know what
> libraries a binary in the ndk links against... Right now I can do this on my distro:
>
> $ ldd aosp/prebuilts/build-tools/linux-x86/bin/toybox
>         linux-vdso.so.1 (0x00007ffd5c7d6000)
>         libcrypto-host.so =>
> /home/android/aosp/prebuilts/build-tools/linux-x86/bin/../lib64/libcrypto-host.so (0x00007f874e908000)
>         libz-host.so =>
> /home/android/aosp/prebuilts/build-tools/linux-x86/bin/../lib64/libz-host.so
> (0x00007f874e8ec000)
>         libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f874e8c7000)
>         libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f874e8a6000)
>         libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f874e723000)
>         librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f874e717000)
>         libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f874e6fd000)
>         libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f874e53c000)
>         libc++.so =>
> /home/android/aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so
> (0x00007f874e457000)
>         /lib64/ld-linux-x86-64.so.2 (0x00007f874eb10000)
>
> Because it's glibc. But if I run the musl ldd such as available on alpine linux:
>
> $ ./ldd aosp/prebuilts/build-tools/linux-x86/bin/toybox
>         /lib64/ld-linux-x86-64.so.2 (0x7ff67053e000)
>         libcrypto-host.so =>
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/libcrypto-host.so (0x7ff670383000)
>         libz-host.so => aosp/prebuilts/build-tools/linux-x86/bin/../lib64/libz-host.so
> (0x7ff670768000)
>         libdl.so.2 => /lib64/ld-linux-x86-64.so.2 (0x7ff67053e000)
>         libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x7ff67053e000)
>         libm.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7ff67053e000)
>         librt.so.1 => /lib64/ld-linux-x86-64.so.2 (0x7ff67053e000)
> Error loading shared library libgcc_s.so.1: No such file or directory (needed by
> aosp/prebuilts/build-tools/linux-x86/bin/toybox)
>         libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7ff67053e000)
>         libc++.so =>
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so
> (0x7ff670683000)
> Error loading shared library libgcc_s.so.1: No such file or directory (needed by
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/libcrypto-host.so)
> Error loading shared library libgcc_s.so.1: No such file or directory (needed by
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/libz-host.so)
> Error loading shared library libgcc_s.so.1: No such file or directory (needed by
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so)
> Error loading shared library ld-linux-x86-64.so.2: No such file or directory
> (needed by aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so)
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/libcrypto-host.so:
> __vsnprintf_chk: symbol not found
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/libcrypto-host.so:
> __memset_chk: symbol not found
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/libcrypto-host.so:
> __memcpy_chk: symbol not found
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/libcrypto-host.so:
> __fprintf_chk: symbol not found
> Error relocating aosp/prebuilts/build-tools/linux-x86/bin/../lib64/libz-host.so:
> __snprintf_chk: symbol not found
> Error relocating aosp/prebuilts/build-tools/linux-x86/bin/../lib64/libz-host.so:
> __vsnprintf_chk: symbol not found
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so:
> __vfprintf_chk: symbol not found
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so:
> _Unwind_Resume: symbol not found
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so:
> __memmove_chk: symbol not found
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so:
> _Unwind_RaiseException: symbol not found
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so:
> _Unwind_DeleteException: symbol not found
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so:
> _Unwind_SetGR: symbol not found
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so:
> _Unwind_SetIP: symbol not found
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so:
> _Unwind_GetLanguageSpecificData: symbol not found
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so:
> _Unwind_GetIP: symbol not found
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so:
> _Unwind_GetRegionStart: symbol not found
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so:
> __vsnprintf_chk: symbol not found
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so:
> __vasprintf_chk: symbol not found
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so: strtoll_l:
> symbol not found
> Error relocating
> aosp/prebuilts/build-tools/linux-x86/bin/../lib64/../lib64/libc++.so:
> strtoull_l: symbol not found
> Error relocating aosp/prebuilts/build-tools/linux-x86/bin/toybox: __fprintf_chk:
> symbol not found
> Error relocating aosp/prebuilts/build-tools/linux-x86/bin/toybox:
> __vfprintf_chk: symbol not found
> Error relocating aosp/prebuilts/build-tools/linux-x86/bin/toybox: __sprintf_chk:
> symbol not found
> Error relocating aosp/prebuilts/build-tools/linux-x86/bin/toybox: __printf_chk:
> symbol not found
> Error relocating aosp/prebuilts/build-tools/linux-x86/bin/toybox:
> __snprintf_chk: symbol not found
> Error relocating aosp/prebuilts/build-tools/linux-x86/bin/toybox: __vsyslog_chk:
> symbol not found
> Error relocating aosp/prebuilts/build-tools/linux-x86/bin/toybox: __longjmp_chk:
> symbol not found
> Error relocating aosp/prebuilts/build-tools/linux-x86/bin/toybox:
> __vsnprintf_chk: symbol not found
> Error relocating aosp/prebuilts/build-tools/linux-x86/bin/toybox: __vprintf_chk:
> symbol not found
> Error relocating aosp/prebuilts/build-tools/linux-x86/bin/toybox: __dprintf_chk:
> symbol not found
> Error relocating aosp/prebuilts/build-tools/linux-x86/bin/toybox: __memcpy_chk:
> symbol not found
> Error relocating aosp/prebuilts/build-tools/linux-x86/bin/toybox: __strcat_chk:
> symbol not found
>
> Not really seeing that as an improvement.

that's because you disagree with the three main (only?) ldds about
what ldd does :-)

> > if you
> > have glibc or musl or bionic, you also have their dynamic linker, and
> > their dynamic linkers act as ldd if asked nicely. (and if you don't
> > have their dynamic linkers, you only have static binaries, so ldd
> > isn't meaningful for you anyway.)
>
> Once upon a time, people did section 4.3.4 of this:
>
> https://tldp.org/HOWTO/Bootdisk-HOWTO/buildroot.html
>
> And I still wind up doing that sort of thing trying to figure out why the
> horrible xilinx webice toolchain isn't working (C++ and shared libraries do not
> mix) or what on earth a squashfs dump from an embedded device is trying to
> connect together...
>
> >> Admittedly, I wasn't trying to get vdso info out of it. I'll take you're word
> >> they've grown more bells and whistles since, and am curious what those are?
> >
> > (see above, but, yes, "what [if anything] did the linker do about the
> > vdso" is another interesting question. though i'd hope anyone not
> > personally maintaining a dynamic linker never needs it for that :-) )
>
> I've hand-collated /proc/$PID/maps output with readelf output to ask gdb to show
> me the appropriate bytes on a SIGSTOPped program. I've written tools to parse
> smaps output. I've run stuff under user mode linux and qemu's jtag-ish -s debug
> mode to get out info I couldn't from a running kernel. (Even kgdb a couple times
> but less often than _actual_ jtag debuggers hooked up to openocd or some
> horrible proprietary thing.)
>
> I may not be a good baseline for "they'll never need that". I've stuck printfs
> into more than one board's stage 1 bootloader (spinning on "output byte to
> register" and "wait for bit to clear so I can send next byte"). I stuck printfs
> into the uClibc dynamic loader to debug its relocation of _itself_. I've worked
> out the constant to subtract from "string" to compensate for the "copy from
> flash to sram" it hasn't done yet but the symbol tables think it has.

(see my earlier comment about the value to people who know what
they're doing < the added confusion for those who don't.)

> >> Rich implemented his ldd as "make a symlink called ldd pointing at the dynamic
> >> linker and it notices the argv[0] name and acts like ldd":
> >>
> >>   http://git.musl-libc.org/cgit/musl/tree/ldso/dynlink.c?h=v1.2.2#n1793
> >>
> >> Even if I _didn't_ suggest it to him back in the day (don't remember), given my
> >> biases I just thought he was doing that old trick to reuse code. (Which
> >> historically busybox copied from gzip/gunzip being hardlinked and supplying -d
> >> to itself based on the name back in 1995, and I'm told there were unix v6
> >> commands doing that back in the 1970s...)
> >
> > i can't speak for him, but for us it was definitely a "this is
> > *really* complicated, and the only realistic way to do it is either
> > build the linker twice, once with an exit() and once with a jump to
> > main(), or reuse the same binary". that wasn't a particular hard
> > choice :-)
>
> I was thinking "better syntax for objdump | grep when dealing with a
> half-finished foreign chroot" since we've already got ELF parsing code in find
> and readelf.
>
> You seem to be thinking of something that almost needs to solve the halting
> problem to figure out what new way du jour android package authors manage to
> screw up their builds.

no, i'm saying "80% of people who ask me for 'an ldd i can run on the
host' are *actually* looking for that verification tool instead".

just you talking about it is giving me nightmares[1]. i already have a
hard enough time trying to explain to these people that (a) that's
basically a shell one-liner but (b) it wouldn't even find the specific
problem with their apk that made them claim to need it, let alone any
of the other common ones. (the worst part of all this being that i
genuinely don't think there's a decent *host* implementation of this,
or we'd have written it already. "you need to test on the OS releases
you claim to support" is annoying, sure, but i'm pretty sure it's a
fact of life.)

> I don't think those are the same tool? The tool I'm describing is an 80/20
> implementation of ldd, using code that's mostly already been written. Yours
> sounds like a very android-specific ELF version of lint/sparse that's aware of
> selinux context and api versions with heuristics to notice contamination from
> windows and glibc and check within uninstalled packages for missing files.
>
> >> Rob
>
> Still Rob

____
1. although one possibility is that they stop bothering us and start
bothering you instead, sadly i doubt that and suspect that i spend my
time explaining why we won't be adding "toybox ldd" to the NDK...


More information about the Toybox mailing list