Date: Monday, August 13, 2007 @ 08:46:13
Author: marc
Path: /cvsroot/carob/libmysequoia/doc
Added: LD_PRELOAD-doc.txt (1.1)
First version
--------------------+
LD_PRELOAD-doc.txt | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 169 insertions(+)
Index: libmysequoia/doc/LD_PRELOAD-doc.txt
diff -u /dev/null libmysequoia/doc/LD_PRELOAD-doc.txt:1.1
--- /dev/null Mon Aug 13 08:46:13 2007
+++ libmysequoia/doc/LD_PRELOAD-doc.txt Mon Aug 13 08:46:12 2007
@@ -0,0 +1,169 @@
+
+ LD_PRELOAD and libmysequoia
+ ---------------------------
+
+
+$Revision: 1.1 $ $Date: 2007/08/13 12:46:12 $ Marc.Herbert at continuent.com
+
+
+Shared objects versus static linking
+------------------------------------
+
+libmysequoia.so is designed to intercept some (but not all) functions
+and other symbols of the original libmysqlclient.so. The ELF
+specification provides the "LD_PRELOAD" environment variable, designed
+expressly for this. So in a perfect world, doing this is enough to use
+libmysequoia:
+
+ LD_PRELOAD=/your/path/to/libmysequoia.so.NN your_application_binary
+
+In a perfect world, you could delete all the rest of this document.
+
+However this does work only if your_application_binary is using
+libmysqlclient.so shared object, as opposed to being statically linked
+to the libmysqlclient.a library. That is, it works if and only if
+your_application_binary does NOT embed code from libmysqlclient.a. In
+this latter and unlikely "static linking" case, recompiling
+your_application_binary is unfortunately required to use
+libmysequoia. There is no way to intercept statically linked/embedded
+code, ever.
+
+If your_application_binary has been compiled by your system
+distributor, then you can be 99.9% sure that it is NOT statically
+linked to libmysqlclient.a. Doing so would be a maintenance nightmare.
+Think for instance about distributing a security update for
+libmysqlclient.
+
+Unfortunately there is no straight-forward one-line command to assert
+if your_application_binary is statically linked to libmysqlclient or
+is using the libmysqlclient.so shared object. First, try to run:
+
+ ldd your_application_binary
+
+If "libmysqclient.so" appears in ldd output, then you know for sure:
+this demonstrates that libmysqclient.so shared object is a mandatory
+dependency of your_application_binary, loaded at start-up time. You
+can skip to the next section.
+
+But if not, you unfortunately still cannot decide yet. That is because
+libmysqlclient.so can either be an _optional_, "plugin" dependency of
+your_application_binary, loaded later at runtime using "dlopen()". Or
+it can embed code from libmysqlclient.a. Harder to tell (Reminder:
+unless you compiled your_application_binary by yourself, the latter is
+very unlikely.)
+
+To avoid making this document too long with copy/paste, techniques to
+answer this "plugin vs statically linked" question will not be
+detailed here, just briefly pointed to below. Please refer to the
+documentation of the tools mentioned for more details.
+
+1. Run "nm -D your_application_binary" and search for defined
+"mysql_..." symbols. your_application_binary embeds code from
+libmysqlclient.a if and only if you find many of them in the output.
+
+2. Alternatively starting your application like this:
+
+ LD_DEBUG=files LD_DEBUG_OUTPUT=/tmp/ld.debug your_application_binary
+
+will dump into "/tmp/ld.debug.NNN" files the names of all shared
+objects (.so) files used, both at startup and at runtime. LD_DEBUG
+is available on linux and solaris at least. Your mileage may vary.
+
+3. Finally you can also try a "brute force" approach. Suppress all
+libmysqlclient.so instances from your system, and try to make your
+application access MySQL. If it fails, your application was using
+libmysqlclient.so
+
+
+
+LD_PRELOAD propagation to forked/sub-processes
+----------------------------------------------
+
+LD_PRELOAD being an environment variable, it is by default propagated
+to all forked subprocesses, which "inherit" it. The end effect is that
+all subprocesses forked by your_application_binary will also pre-load
+the libmysequoia.so library. In most cases, this should harmless. You
+might even like it if you want your subprocesses to also use
+libmysequoia instead of libmysql.
+
+However in some cases this might cause problems (see next section for
+instance). To avoid these, "simply" unset the LD_PRELOAD variable in
+your application. For instance with PHP, add this line at the very
+beginning of your code:
+
+ putenv("LD_PRELOAD=");
+
+
+
+The RTLD_DEEPBIND bug (PHP)
+---------------------------
+
+The ELF specification grants a higher priority to symbols loaded at
+startup time (global scope) compared to symbols loaded at run-time
+(plugins's local scopes), even when solving symbols for plugins
+themselves. This is required for LD_PRELOAD=libmysequoia.so to
+also intercept plugins.
+
+However PHP libraries and plugins often have symbol
+collisions/conflicts problems, due to the lack of proper
+namespaces. To workaround the lack of namespaces most PHP versions are
+using a tricky and poorly documented linux-specific flag called
+RTLD_DEEPBIND <http://marc.info/?t=116196475300004&r=1&w=2>
+<http://cygwin.com/ml/libc-hacker/2004-09/msg00083.html>
+
+By changing the symbol lookup order, RTLD_DEEPBIND totally breaks
+"LD_PRELOAD=libmysequoia.so"
+
+
+So far there are three known solutions for the RTLD_DEEPBIND bug.
+
+1. LD_PRELOAD="path/to/libmysequoia.so:path/to/mysqli.so"
+Since shared objects are loaded only once, the later
+DL_LOAD(RTLD_DEEPBIND) issued by PHP will be ignored. This is probably
+the safest solution. However you will need to stop propagation of
+LD_PRELOAD as explained in the previous section. This is because
+mysql[i].so can be loaded ONLY with the main PHP binary due to
+back-references to it!
+
+2. Remove RTLD_DEEPBIND from the definition of DL_LOAD in zend.h and
+recompile PHP. However, if you are using several conflicting PHP
+modules at the same time, PHP will crash.
+
+3. Recompile mysql[i].so and link it explicitely to libmysequoia. Use
+the "mysequoia_config" script provided here instead of the
+"mysql_config" script.
+
+
+References
+----------
+
+Of course first check the documentation of your system. Start by
+looking for "ld.so" and "dlopen".
+
+Sun Microsystems' "Linker and Libraries Guide" provides a good on-line
+introduction to ELF shared objects. The "Runtime Linking Programming
+Interface" section details a typical ELF symbol lookup scheme.
+
+"How to Write Shared Libraries" by Ulrich Drepper also provides bits
+of relevant information.
+
+
+Debugging
+---------
+
+On system using GNU libc, notably linux, you can trace all shared
+objects-related events by starting your application like this:
+
+LD_DEBUG=symbols,bindings LD_DEBUG_OUTPUT=/tmp/ld.debug
your_application_binary
+
+For more details, search the web for "LD_DEBUG".
+
+
+Testing
+-------
+
+The ldtest/ provides some sample C code and scripts to help you test
+how your system behaves with respect to shared objects linking.
+
+
+
_______________________________________________
Carob-commits mailing list
[email protected]
https://forge.continuent.org/mailman/listinfo/carob-commits