when is the environ symbol defined in the executable?
2
votes
0
answers
109
views
If I compile a simple test program, I get environment symbols defined (and exported) in the executable itself:
root@4ef8c4a55769:/# clang --version
Debian clang version 11.0.1-2
Target: aarch64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
root@4ef8c4a55769:/# cat /tmp/a.c
#include
extern const char *const * __environ;
int main() {
if (!__environ) {
return 1;
}
for (__auto_type p = __environ; *p; p++) {
puts(*p);
}
return 0;
}
root@4ef8c4a55769:/# clang /tmp/a.c
root@4ef8c4a55769:/# ./a.out
_=./a.out
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SHLVL=1
TERM=xterm
HOME=/root
PWD=/
HOSTNAME=4ef8c4a55769
root@4ef8c4a55769:/# readelf --wide --dyn-syms a.out | grep environ
5: 0000000000411030 8 OBJECT WEAK DEFAULT 25 _environ@GLIBC_2.17 (2)
6: 0000000000411030 8 OBJECT WEAK DEFAULT 25 environ@GLIBC_2.17 (2)
7: 0000000000411030 8 OBJECT GLOBAL DEFAULT 25 __environ@GLIBC_2.17 (2)
this is despite the fact that glibc itself defines these:
root@4ef8c4a55769:/# readelf --dyn-syms --wide /lib/aarch64-linux-gnu/libc.so.6 | grep environ
296: 0000000000172658 8 OBJECT WEAK DEFAULT 31 _environ@@GLIBC_2.17
1007: 0000000000172658 8 OBJECT WEAK DEFAULT 31 environ@@GLIBC_2.17
1334: 0000000000172658 8 OBJECT GLOBAL DEFAULT 31 __environ@@GLIBC_2.17
however, I have executables where this is imported (including one program I compiled myself, though the same program compiled with the same compiler but on amd64 still defines environ):
root@4ef8c4a55769:/# readelf --wide --dyn-syms /bin/bash | grep environ
123: 0000000000000000 0 OBJECT WEAK DEFAULT UND _environ@GLIBC_2.17 (2)
185: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND __environ@GLIBC_2.17 (2)
191: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND environ@GLIBC_2.17 (2)
...
To have it imported is my desired behavior. The reason is that I get incorrect runtime linking (as seen with LD_DEBUG
) when there are two __environ
symbols: libc binds to the executable, but the executable and later loaded dynamic libraries bind to libc. This results in the __environ
from the executable being populated, but not the one defined in libc.
My question is: what determines this behavior, and how can I force __environ
imported?
EDIT:
Interestingly, if I compile with GCC the symbols don't get defined (though on amd64 they are still defined):
root@4ef8c4a55769:/# gcc --version
gcc (Debian 10.2.1-6) 10.2.1 20210110
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
The link line for gcc is:
/usr/lib/gcc/aarch64-linux-gnu/10/collect2 -plugin /usr/lib/gcc/aarch64-linux-gnu/10/liblto_plugin.so -plugin-opt=/usr/lib/gcc/aarch64-linux-gnu/10/lto-wrapper -plugin-opt=-fresolution=/tmp/ccnbGUtW.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr --hash-style=gnu --as-needed -dynamic-linker /lib/ld-linux-aarch64.so.1 -X -EL -maarch64linux --fix-cortex-a53-843419 -pie /usr/lib/gcc/aarch64-linux-gnu/10/../../../aarch64-linux-gnu/Scrt1.o /usr/lib/gcc/aarch64-linux-gnu/10/../../../aarch64-linux-gnu/crti.o /usr/lib/gcc/aarch64-linux-gnu/10/crtbeginS.o -L/usr/lib/gcc/aarch64-linux-gnu/10 -L/usr/lib/gcc/aarch64-linux-gnu/10/../../../aarch64-linux-gnu -L/usr/lib/gcc/aarch64-linux-gnu/10/../../../../lib -L/lib/aarch64-linux-gnu -L/lib/../lib -L/usr/lib/aarch64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/aarch64-linux-gnu/10/../../.. /tmp/cccSV4NT.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/aarch64-linux-gnu/10/crtendS.o /usr/lib/gcc/aarch64-linux-gnu/10/../../../aarch64-linux-gnu/crtn.o
and for clang:
"/usr/bin/ld" -EL --hash-style=both --build-id --eh-frame-hdr -m aarch64linux -dynamic-linker /lib/ld-linux-aarch64.so.1 -o a.out /usr/bin/../lib/gcc/aarch64-linux-gnu/10/../../../aarch64-linux-gnu/crt1.o /usr/bin/../lib/gcc/aarch64-linux-gnu/10/../../../aarch64-linux-gnu/crti.o /usr/bin/../lib/gcc/aarch64-linux-gnu/10/crtbegin.o -L/usr/bin/../lib/gcc/aarch64-linux-gnu/10 -L/usr/bin/../lib/gcc/aarch64-linux-gnu/10/../../../aarch64-linux-gnu -L/lib/aarch64-linux-gnu -L/usr/lib/aarch64-linux-gnu -L/usr/bin/../lib/gcc/aarch64-linux-gnu/10/../../.. -L/usr/lib/llvm-11/bin/../lib -L/lib -L/usr/lib /tmp/a-06a7fe.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/bin/../lib/gcc/aarch64-linux-gnu/10/crtend.o /usr/bin/../lib/gcc/aarch64-linux-gnu/10/../../../aarch64-linux-gnu/crtn.o
Asked by Artefacto
(255 rep)
Jul 10, 2024, 11:46 PM
Last activity: Jul 10, 2024, 11:53 PM
Last activity: Jul 10, 2024, 11:53 PM