On 8/29/2014 12:23 PM, Konstantin Belousov wrote: > On Fri, Aug 29, 2014 at 09:57:31AM -0500, Bryan Drewery wrote: >> On 8/29/2014 5:44 AM, Konstantin Belousov wrote: >>> Author: kib >>> Date: Fri Aug 29 10:44:58 2014 >>> New Revision: 270803 >>> URL: http://svnweb.freebsd.org/changeset/base/270803 >>> >>> Log: >>> Document the whole settings needed to build a debug version of rtld. >>> >>> Sponsored by: The FreeBSD Foundation >>> MFC after: 3 days >>> >>> Modified: >>> head/libexec/rtld-elf/Makefile >>> >>> Modified: head/libexec/rtld-elf/Makefile >>> ============================================================================== >>> --- head/libexec/rtld-elf/Makefile Fri Aug 29 10:43:56 2014 >>> (r270802) >>> +++ head/libexec/rtld-elf/Makefile Fri Aug 29 10:44:58 2014 >>> (r270803) >>> @@ -1,5 +1,9 @@ >>> # $FreeBSD$ >>> >>> +# Use the following command to build local debug version of dynamic >>> +# linker: >>> +# make DEBUG_FLAGS=-g DEBUG=-DDEBUG MK_TESTS=no all >>> + >>> .include <src.opts.mk> >>> MK_SSP= no >>> >>> >> >> How difficult would it be to allow DEBUG to be set during runtime like >> GNU's can with LD_DEBUG? I have found GNU's LD_DEBUG to be very useful >> for userland debugging, especially when using dlopen(3). >> >> We have LD_DEBUG environment variable but it only prints if built with >> -DDEBUG. >> >> Is there a concern about performance by enabling this based only on >> environment? > > I am sure that nobody evaluated the performance consequences of > unconditionally compiling the debugging stuff in. I am sure that the > ld-elf.so.1 size will increase. > > The reason why nobody cares to evaluate and enable this stuff by default > is that the debugging output is very ad-hoc. I found it almost useless > in both the content and amount of data it outputs. The reason why I > enable it for my work on ld-elf is that I insert my own dbg() calls for > debugging (and usually remove them before the commit since they add even > more verbosity useless for general public consumption).
Ah. > > I find the combination of the ELF dumping tools like readelf and > objdump, together with gdb (-g) and custom dbg() statement (slighly > glorified printf debugging) most adequate combination to debug rtld. > > After the long preamble. What use do you have for LD_DEBUG ? If it is > possible to formalize and tailor the debugging output for real users > needs, I am all for making it available unconditionally from LD_DEBUG > knob. The significants part of the current dbg() statements would be > removed or require more agressive settings to become active. > My only uses so far have been observing which file is loaded for a library with dlopen(3) and where symbols are resolved from. Seeing where symbols are resolved from is useful for both dlopen(3)/dlsym(3) usage and LD_PRELOAD. I've written an application that "optionally" allows using some libraries such as libtcl to be used without requiring the library at build time or startup. At build time the library's headers are used to generate wrapper functions for every symbol needed. The library is not linked in. When the binary is ran it starts up fine if libtcl is missing. At runtime if TCL is enabled then it will attempt to dlopen(libtcl.so.VER) using the VER its symbols was compiled against. If it cannot find it then the feature is disabled. It uses dlsym(3) to load all symbols into a table and the wrapper functions use that table via hash table lookups. This all pretty convoluted and only done to avoid requiring a library at startup. The application is distributed pre-compiled for specific OS releases and not intended to be compiled manually. Anyway some examples from GNU's rtld: > # env LD_DEBUG=help ./app > Valid options for the LD_DEBUG environment variable are: > > libs display library search paths > reloc display relocation processing > files display progress for input file > symbols display symbol table processing > bindings display information about symbol binding > versions display version dependencies > all all previous options combined > statistics display relocation statistics > unused determined unused DSOs > help display this help message and exit > > To direct the debugging output into a file instead of standard output > a filename can be specified using the LD_DEBUG_OUTPUT environment variable. With libs: > # env LD_DEBUG=libs ./app > ... > 9328: find library=libtcl.so [0]; searching > 9328: search cache=/etc/ld.so.cache > 9328: search > path=/lib64/tls/x86_64:/lib64/tls:/lib64/x86_64:/lib64:/usr/lib64/tls/x86_64:/usr/lib64/tls:/usr/lib64/x86_64:/usr/lib64 > (system search path) > 9328: trying file=/lib64/tls/x86_64/libtcl.so > 9328: trying file=/lib64/tls/libtcl.so > 9328: trying file=/lib64/x86_64/libtcl.so > 9328: trying file=/lib64/libtcl.so > 9328: trying file=/usr/lib64/tls/x86_64/libtcl.so > 9328: trying file=/usr/lib64/tls/libtcl.so > 9328: trying file=/usr/lib64/x86_64/libtcl.so > 9328: trying file=/usr/lib64/libtcl.so > 9328: > 9328: find library=libpthread.so.0 [0]; searching > 9328: search path=/usr/lib64 (system search path) > 9328: trying file=/usr/lib64/libpthread.so.0 > 9328: search cache=/etc/ld.so.cache > 9328: trying file=/lib64/libpthread.so.0 > 9328: > 9328: > 9328: calling init: /lib64/libpthread.so.0 > 9328: > 9328: > 9328: calling init: /usr/lib64/libtcl.so > 9328: > 9328: find library=libnss_compat.so.2 [0]; searching > 9328: search cache=/etc/ld.so.cache > 9328: trying file=/lib64/libnss_compat.so.2 > 9328: > 9328: find library=libnsl.so.1 [0]; searching > 9328: search cache=/etc/ld.so.cache > 9328: trying file=/lib64/libnsl.so.1 > 9328: > 9328: > 9328: calling init: /lib64/libnsl.so.1 > 9328: > 9328: > 9328: calling init: /lib64/libnss_compat.so.2 > 9328: > 9328: find library=libnss_nis.so.2 [0]; searching > 9328: search cache=/etc/ld.so.cache > 9328: trying file=/lib64/libnss_nis.so.2 > 9328: > 9328: find library=libnss_files.so.2 [0]; searching > 9328: search cache=/etc/ld.so.cache > 9328: trying file=/lib64/libnss_files.so.2 > 9328: > 9328: > 9328: calling init: /lib64/libnss_files.so.2 > 9328: > 9328: > 9328: calling init: /lib64/libnss_nis.so.2 > ^C > 9328: calling fini: /usr/lib64/libtcl.so [0] > 9328: > 9328: > 9328: calling fini: /lib64/libm.so.6 [0] > 9328: > 9328: > 9328: calling fini: /lib64/libdl.so.2 [0] > 9328: > 9328: > 9328: calling fini: /lib64/libpthread.so.0 [0] > 9328: > 9328: > 9328: calling fini: /lib64/libnss_compat.so.2 [0] > 9328: > 9328: > 9328: calling fini: /lib64/libnss_nis.so.2 [0] > 9328: > 9328: > 9328: calling fini: /lib64/libnsl.so.1 [0] > 9328: > 9328: > 9328: calling fini: /lib64/libnss_files.so.2 [0] > 9328: > 9328: > 9328: calling fini: /lib64/libc.so.6 [0] With symbols: > # LD_DEBUG=symbols ./app > ... > 9355: symbol=Tcl_SetObjResult; lookup in file=/lib64/libdl.so.2 [0] > 9355: symbol=Tcl_SetObjResult; lookup in > file=/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2/libstdc++.so.6 [0] > 9355: symbol=Tcl_SetObjResult; lookup in file=/lib64/libm.so.6 [0] > 9355: symbol=Tcl_SetObjResult; lookup in > file=/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2/libgcc_s.so.1 [0] > 9355: symbol=Tcl_SetObjResult; lookup in file=/lib64/libc.so.6 [0] > 9355: symbol=Tcl_SetObjResult; lookup in > file=/lib64/ld-linux-x86-64.so.2 [0] > 9355: symbol=Tcl_SetObjResult; lookup in > file=/usr/lib64/libcrypto.so.1.0.0 [0] > 9355: symbol=Tcl_SetObjResult; lookup in file=/lib64/libz.so.1 [0] > 9355: symbol=Tcl_SetObjResult; lookup in file=/usr/lib64/libtcl.so > [0] > 9355: symbol=Tcl_GetObjResult; lookup in file=./netplay [0] > 9355: symbol=Tcl_GetObjResult; lookup in file=/lib64/libdl.so.2 [0] > 9355: symbol=Tcl_GetObjResult; lookup in > file=/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2/libstdc++.so.6 [0] > 9355: symbol=Tcl_GetObjResult; lookup in file=/lib64/libm.so.6 [0] > 9355: symbol=Tcl_GetObjResult; lookup in > file=/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.2/libgcc_s.so.1 [0] > 9355: symbol=Tcl_GetObjResult; lookup in file=/lib64/libc.so.6 [0] > 9355: symbol=Tcl_GetObjResult; lookup in > file=/lib64/ld-linux-x86-64.so.2 [0] > 9355: symbol=Tcl_GetObjResult; lookup in > file=/usr/lib64/libcrypto.so.1.0.0 [0] > 9355: symbol=Tcl_GetObjResult; lookup in file=/lib64/libz.so.1 [0] > 9355: symbol=Tcl_GetObjResult; lookup in file=/usr/lib64/libtcl.so > [0] I would love to work on adding such a feature to ours, especially if it can assist with debugging rtld itself. I would think with some predict_false() checks we could avoid much of the performance penalties. As a side note I think I may have found an rtld issue (on 8.4) with -32 handling. Being a production machine I don't want to attempt installing a DEBUG rtld to figure out the problem. Having LD_DEBUG would have been useful on this as well. The issue I ran into with -32 was from converting a i386 system to amd64. I have hundreds of out-of-ports binaries that need to be manually recompiled. To allow delaying this task for a bit I copied all of the libraries from /usr/local/lib from the old i386 system to /usr/local/lib32/compat/system and added all of the paths in there to ldconfig: > [~] # ldconfig -32 -r|head -n3 > /var/run/ld-elf32.so.hints: > search directories: > /usr/lib32:/usr/local/lib32/compat/system:/usr/local/lib32/compat/system/mysql:/usr/local/lib32/compat/system/gnutls3:/usr/local/lib32/compat/system/pth:/usr/local/lib32/compat/system/qt4:/usr/local/lib32/compat/system/tdom0.8.3:/usr/local/lib32/compat/system/gcc46:/usr/local/lib32/compat/system/gcc47:/usr/local/lib32/compat/system/gcc48:/usr/local/lib32/compat/system/gcc49:/usr/local/lib32/compat/system/event2:/usr/local/lib32/compat/pkg:/usr/local/lib32/compat It worked for 90% of the system but then I ran into some libraries that refused to find their own dependencies. The issue seemingly is that dependencies for libraries that are also in the -32 path are not looked up. For example: > [~] # ldd -a /usr/local/lib32/compat/system/libssl.so > /usr/local/lib32/compat/system/libssl.so: > libcrypto.so.8 => not found (0x0) > libthr.so.3 => /usr/lib32/libthr.so.3 (0x310fb000) > libc.so.7 => /usr/lib32/libc.so.7 (0x29165000) > /usr/lib32/libthr.so.3: > libc.so.7 => /usr/lib32/libc.so.7 (0x29165000) > [~] # ldconfig -32 -r|grep libcrypto.so.8 > 105:-lcrypto.8 => /usr/local/lib32/compat/system/libcrypto.so.8 > [~] # readelf -a /usr/local/lib32/compat/system/libssl.so|egrep > "(path|NEEDED)" > 0x00000001 (NEEDED) Shared library: [libcrypto.so.8] > 0x00000001 (NEEDED) Shared library: [libthr.so.3] > 0x00000001 (NEEDED) Shared library: [libc.so.7] > 0x0000000f (RPATH) Library rpath: [/usr/local/lib] My guess is it is the RPATH. I am not sure without a simple debug ability. -- Regards, Bryan Drewery
signature.asc
Description: OpenPGP digital signature