MINOR: debug: add support for -dL to dump library names at boot

This is a second help to dump loaded library names late at boot, once
external code has already been initialized. The purpose is to provide
a format that makes it easy to pass to "tar" to produce an archive
containing the executable and the list of dependencies. For example
if haproxy is started as "haproxy -f foo.cfg", a config check only
will suffice to quit before starting, "-q" will be used to disable
undesired output messages, and -dL will be use to dump libraries.
This will result in such a command to trivially produce a tarball
of loaded libraries:

   ./haproxy -q -c -dL -f foo.cfg | tar -T - -hzcf archive.tgz
This commit is contained in:
Willy Tarreau 2021-12-28 15:43:11 +01:00
parent 6ab7b21a11
commit 654726db5a
3 changed files with 31 additions and 1 deletions

View File

@ -213,6 +213,19 @@ list of options is :
getaddrinfo() exist on various systems and cause anomalies that are
difficult to troubleshoot.
-dL : dumps the list of dynamic shared libraries that are loaded at the end
of the config processing. This will generally also include deep dependencies
such as anything loaded from Lua code for example, as well as the executable
itself. The list is printed in a format that ought to be easy enough to
sanitize to directly produce a tarball of all dependencies. Since it doesn't
stop the program's startup, it is recommended to only use it in combination
with "-c" and "-q" where only the list of loaded objects will be displayed
(or nothing in case of error). In addition, keep in mind that when providing
such a package to help with a core file analysis, most libraries are in fact
symbolic links that need to be dereferenced when creating the archive:
./haproxy -W -q -c -dL -f foo.cfg | tar -T - -hzcf archive.tgz
-dM[<byte>] : forces memory poisoning, which means that each and every
memory region allocated with malloc() or pool_alloc() will be filled with
<byte> before being passed to the caller. When <byte> is not specified, it

View File

@ -40,6 +40,7 @@
#define MODE_DIAG 0x400 /* extra warnings */
#define MODE_CHECK_CONDITION 0x800 /* -cc mode */
#define MODE_STOPPING 0x1000 /* the process is in the deinit phase, the event loop is not running anymore. */
#define MODE_DUMP_LIBS 0x2000 /* dump loaded libraries at the end of init phase */
/* list of last checks to perform, depending on config options */
#define LSTCHK_CAP_BIND 0x00000001 /* check that we can bind to any port */

View File

@ -596,6 +596,9 @@ static void usage(char *name)
#endif
#if defined(SO_REUSEPORT)
" -dR disables SO_REUSEPORT usage\n"
#endif
#if defined(HA_HAVE_DUMP_LIBS)
" -dL dumps loaded object files after config checks\n"
#endif
" -dr ignores server address resolution failures\n"
" -dV disables SSL verify on servers side\n"
@ -1632,6 +1635,10 @@ static void init(int argc, char **argv)
mem_poison_byte = flag[2] ? strtol(flag + 2, NULL, 0) : 'P';
else if (*flag == 'd' && flag[1] == 'r')
global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
#if defined(HA_HAVE_DUMP_LIBS)
else if (*flag == 'd' && flag[1] == 'L')
arg_mode |= MODE_DUMP_LIBS;
#endif
else if (*flag == 'd')
arg_mode |= MODE_DEBUG;
else if (*flag == 'c' && flag[1] == 'c') {
@ -1773,7 +1780,7 @@ static void init(int argc, char **argv)
global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
| MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
| MODE_DIAG | MODE_CHECK_CONDITION));
| MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS));
if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
@ -2056,6 +2063,15 @@ static void init(int argc, char **argv)
exit(1);
}
#if defined(HA_HAVE_DUMP_LIBS)
if (global.mode & MODE_DUMP_LIBS) {
qfprintf(stdout, "List of loaded object files:\n");
chunk_reset(&trash);
if (dump_libs(&trash, 0))
printf("%s", trash.area);
}
#endif
if (global.mode & MODE_CHECK) {
struct peers *pr;
struct proxy *px;