LD: always magical

I was reading lwn articles recently and saw a post pointing to and quoting a well versed walk through of processes' lifecycle on Linux.

Their excerpt included a bit about setting LD_SHOW_AUXV to make ld (I think? I opened the tab in the background to read...). This was immediately interesting to me: any time that someone is sharing their own hard earned understanding LD.. I listen well! There's a lot of engineering behind the likes of ld and linux (naturally!) – in this case, the tip to use this environment variable was immediately at hand:

I ran sh with the variable exported on my system:

❯ LD_SHOW_AUXV=1 /bin/sh 
AT_SYSINFO_EHDR:      0x7ffed19db000
AT_HWCAP:             bfebfbff
AT_PAGESZ:            4096
AT_CLKTCK:            100
AT_PHDR:              0x400040
AT_PHENT:             56
AT_PHNUM:             11
AT_BASE:              0x7f5004b68000
AT_FLAGS:             0x0
AT_ENTRY:             0x41db30
AT_UID:               1000
AT_EUID:              1000
AT_GID:               100
AT_EGID:              100
AT_SECURE:            0
AT_RANDOM:            0x7ffed19c5f89
AT_HWCAP2:            0x2
AT_EXECFN:            /bin/sh
AT_PLATFORM:          x86_64

Neat! I know most of these short and terse identifiers with others that are new to me. These are the edges of the engineering world I like to find, avenues to explore further to integrate and apply to my own work.

Well, enough of that! What else? Let's try another command, after all the environment variable is exported. How about true – that's pretty trivial.

sh-4.4$ true

But also boring. There's no output. Well, that's because we're probably using bash's builtin true “function”.

sh-4.4$ /run/current-system/sw/bin/true
AT_SYSINFO_EHDR:      0x7ffd951e6000
AT_HWCAP:             bfebfbff
AT_PAGESZ:            4096
AT_CLKTCK:            100
AT_PHDR:              0x400040
AT_PHENT:             56
AT_PHNUM:             11
AT_BASE:              0x7eff8120f000
AT_FLAGS:             0x0
AT_ENTRY:             0x4089c0
AT_UID:               1000
AT_EUID:              1000
AT_GID:               100
AT_EGID:              100
AT_SECURE:            0
AT_RANDOM:            0x7ffd95067819
AT_HWCAP2:            0x2
AT_EXECFN:            /run/current-system/sw/bin/true
AT_PLATFORM:          x86_64

Note: my output says things like /run/current-system/sw/bin/true with that long path because I use NixOS and that's just where its located. Pretend lines like those say /bin/true or /usr/bin/true if that tickles your fancy.

I want to see the opposite now, where nothing is printed out with the environment still configured, because I suspect that this is implemented in glibc based on the little I've actually read of the article (I will read it, eventually).

To do this, I wrote a quick Go program to say hi that I can use static compilation to avoid linking to a libc:

package main

func main() { print("hi there\n") }

I built it:

CGO_ENABLED=0 go build static-go-bin.go

Checked it for riddles:

sh-4.4$ ldd ./static-go-bin
	not a dynamic executable

And then ran it with the environment variable set:

❯ LD_SHOW_AUXV=1 ./static-go-bin 
hi there

Hrm. Okay, nothing printed, but that's not conclusive. We still need to know if its ld or something that ld loaded that makes something print.

You know what, I'm going to stop here and just go read the article! That seems most pragmatic at this point.