2020年12月23日星期三

How can I verify what dynamic linker is used when a program is run?

I would like to verify that the dynamic linker used when a program is run is the one mentioned via file, readelf -l, or ldd. My motivation stems from having multiple dynamic linkers that exist in separate spaces on the machine and they should never mix-and-match.

Thus far, the best way I have found to verify the dynamic linker is via gdb. By looking at output of info proc mappings, I can determine which dynamic linker was mapped into the address space and is in use. I am trying to avoid using gdb as it would require me to run test suites and other things through it.

Using the LD_DEBUG environment variable seems like it could be an alternate solution which would allow me to easily save logs for verification after (or during) program execution. However, I am unsure which option would give me the best information. I thought scopes or libs could be good options but libs doesn't always mention the dynamic linker. For example, this is the output of a simple hello world program:

$ LD_DEBUG=libs ./test0       24579: find library=libc.so.6 [0]; searching       24579:  search cache=/etc/ld.so.cache       24579:   trying file=/lib/x86_64-linux-gnu/libc.so.6       24579:       24579:       24579: calling init: /lib/x86_64-linux-gnu/libc.so.6       24579:       24579:       24579: initialize program: ./test0       24579:       24579:       24579: transferring control: ./test0       24579:  hello world       24579:       24579: calling fini: ./test0 [0]       24579:  $ LD_DEBUG=libs ./test0-gnu-cross       24581: find library=libc.so.6 [0]; searching       24581:  search path=/usr/local/gnu-cross/x86_64-linux-gnu/lib/glibc-hwcaps/x86-64-v4:/usr/local/gnu-cross/x86_64-linux-gnu/lib/glibc-hwcaps/x86-64-v3:/usr/local/gnu-cross/x86_64-linux-gnu/lib/glibc-hwcaps/x86-64-v2:/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/haswell/avx512_1/x86_64:/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/haswell/avx512_1:/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/haswell/x86_64:/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/haswell:/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/avx512_1/x86_64:/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/avx512_1:/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/x86_64:/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls:/usr/local/gnu-cross/x86_64-linux-gnu/lib/haswell/avx512_1/x86_64:/usr/local/gnu-cross/x86_64-linux-gnu/lib/haswell/avx512_1:/usr/local/gnu-cross/x86_64-linux-gnu/lib/haswell/x86_64:/usr/local/gnu-cross/x86_64-linux-gnu/lib/haswell:/usr/local/gnu-cross/x86_64-linux-gnu/lib/avx512_1/x86_64:/usr/local/gnu-cross/x86_64-linux-gnu/lib/avx512_1:/usr/local/gnu-cross/x86_64-linux-gnu/lib/x86_64:/usr/local/gnu-cross/x86_64-linux-gnu/lib     (RPATH from file ./test0-gnu-cross)       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/glibc-hwcaps/x86-64-v4/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/glibc-hwcaps/x86-64-v3/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/glibc-hwcaps/x86-64-v2/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/haswell/avx512_1/x86_64/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/haswell/avx512_1/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/haswell/x86_64/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/haswell/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/avx512_1/x86_64/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/avx512_1/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/x86_64/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/haswell/avx512_1/x86_64/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/haswell/avx512_1/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/haswell/x86_64/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/haswell/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/avx512_1/x86_64/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/avx512_1/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/x86_64/libc.so.6       24581:   trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/libc.so.6       24581:       24581:       24581: calling init: /usr/local/gnu-cross/x86_64-linux-gnu/lib/ld-linux-x86-64.so.2       24581:       24581:       24581: calling init: /usr/local/gnu-cross/x86_64-linux-gnu/lib/libc.so.6       24581:       24581:       24581: initialize program: ./test0-gnu-cross       24581:       24581:       24581: transferring control: ./test0-gnu-cross       24581:  hello world       24581:       24581: calling fini: ./test0-gnu-cross [0]       24581:  

As you can see, the program test0 which is built with a standard Debian/GNU toolchain and uses the system's dynamic linker doesn't state that.

The scopes option looks more helpful but I don't understand what the output is saying:

$ LD_DEBUG=scopes ./test0       24577:       24577: Initial object scopes       24577: object=./test0 [0]       24577:  scope 0: ./test0 /lib/x86_64-linux-gnu/libc.so.6 /lib64/ld-linux-x86-64.so.2       24577:       24577: object=linux-vdso.so.1 [0]       24577:  scope 0: ./test0 /lib/x86_64-linux-gnu/libc.so.6 /lib64/ld-linux-x86-64.so.2       24577:  scope 1: linux-vdso.so.1       24577:       24577: object=/lib/x86_64-linux-gnu/libc.so.6 [0]       24577:  scope 0: ./test0 /lib/x86_64-linux-gnu/libc.so.6 /lib64/ld-linux-x86-64.so.2       24577:       24577: object=/lib64/ld-linux-x86-64.so.2 [0]       24577:  no scope       24577:  hello world  $ LD_DEBUG=scopes ./test0-gnu-cross       24576:       24576: Initial object scopes       24576: object=./test0-gnu-cross [0]       24576:  scope 0: ./test0-gnu-cross /usr/local/gnu-cross/x86_64-linux-gnu/lib/libc.so.6 /usr/local/gnu-cross/x86_64-linux-gnu/lib/ld-linux-x86-64.so.2       24576:       24576: object=linux-vdso.so.1 [0]       24576:  scope 0: ./test0-gnu-cross /usr/local/gnu-cross/x86_64-linux-gnu/lib/libc.so.6 /usr/local/gnu-cross/x86_64-linux-gnu/lib/ld-linux-x86-64.so.2       24576:  scope 1: linux-vdso.so.1       24576:       24576: object=/usr/local/gnu-cross/x86_64-linux-gnu/lib/libc.so.6 [0]       24576:  scope 0: ./test0-gnu-cross /usr/local/gnu-cross/x86_64-linux-gnu/lib/libc.so.6 /usr/local/gnu-cross/x86_64-linux-gnu/lib/ld-linux-x86-64.so.2       24576:       24576: object=/usr/local/gnu-cross/x86_64-linux-gnu/lib/ld-linux-x86-64.so.2 [0]       24576:  no scope       24576:  hello world  

In summary, I would like to find a good way to verify the dynamic linker that is being used. Unless you can think of a better option, LD_DEBUG seems like a good bet, but I struggle to understand how to use it effectively in this case.

Thank you for your help :)

https://stackoverflow.com/questions/65429331/how-can-i-verify-what-dynamic-linker-is-used-when-a-program-is-run December 24, 2020 at 02:41AM

没有评论:

发表评论