Sample Header Ad - 728x90

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