From 9aa50b2ece3e1360d369d07c3ef32c6d67eeb489 Mon Sep 17 00:00:00 2001 From: Angus Salkeld Date: Wed, 6 Apr 2011 22:09:46 +1000 Subject: [PATCH] LOG: fix shared library callsites This finds all the callsites in shared libraries (using dl_iterate_phdr()) at the time qb_log_init() is called. Signed-off-by: Angus Salkeld Conflicts: lib/log.c --- configure.ac | 1 + include/qb/qblog.h | 6 ++++++ lib/libqb.pc.in | 2 +- lib/log.c | 54 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 74debbb..8366888 100644 --- a/configure.ac +++ b/configure.ac @@ -94,6 +94,7 @@ esac # Checks for libraries. AC_CHECK_LIB([rt], [mq_open]) +AC_CHECK_LIB([dl], [dlopen]) AC_CHECK_LIB([pthread], [pthread_create]) AC_CHECK_LIB([socket], [socket]) diff --git a/include/qb/qblog.h b/include/qb/qblog.h index a2facc1..e931652 100644 --- a/include/qb/qblog.h +++ b/include/qb/qblog.h @@ -203,6 +203,12 @@ struct qb_log_callsite { extern struct qb_log_callsite __start___verbose[]; extern struct qb_log_callsite __stop___verbose[]; +#define QB_LOG_INIT_DATA(name) \ + void name(void); \ + void name(void) { assert(__start___verbose != __stop___verbose); } \ + void __attribute__ ((constructor)) name(void); + + /** * Internal function: use qb_log() */ diff --git a/lib/libqb.pc.in b/lib/libqb.pc.in index 6d0963f..8426856 100644 --- a/lib/libqb.pc.in +++ b/lib/libqb.pc.in @@ -7,5 +7,5 @@ Name: libqb Version: @PACKAGE_VERSION@ Description: libqb Requires: -Libs: -L${libdir} -lqb -lrt +Libs: -L${libdir} -lqb -lrt -ldl Cflags: -I${includedir} diff --git a/lib/log.c b/lib/log.c index 0b01c0f..0a71717 100644 --- a/lib/log.c +++ b/lib/log.c @@ -20,7 +20,9 @@ */ #include "os_base.h" #include +#include #include + #include #include #include @@ -211,13 +213,21 @@ void qb_log_callsites_register(struct qb_log_callsite *_start, struct qb_log_cal if (_start == NULL || _stop == NULL) { return; } + + qb_list_for_each_entry(sect, &callsite_sections, list) { + if (sect->start == _start || sect->stop == _stop) { + return; + } + } + sect = calloc(1, sizeof(struct callsite_section)); sect->start = _start; sect->stop = _stop; qb_list_init(§->list); qb_list_add(§->list, &callsite_sections); - /* Now apply the filters on these new callsites + /* + * Now apply the filters on these new callsites */ qb_list_for_each_entry(t, &active_targets, active_list) { qb_list_for_each_entry(flt, &t->filter_head, list) { @@ -315,6 +325,46 @@ int32_t qb_log_filter_ctl(uint32_t t, enum qb_log_filter_conf c, return 0; } +static int32_t +_log_so_walk_callback(struct dl_phdr_info *info, size_t size, void *data) +{ + if (strlen(info->dlpi_name) > 0) { + void *handle; + void *start; + void *stop; + char *error; + + handle = dlopen(info->dlpi_name, RTLD_LAZY); + error = dlerror(); + if (!handle || error) { + qb_log(LOG_ERR, 0, "%s", error); + if(handle) { + dlclose(handle); + } + return 0; + } + + start = dlsym(handle, "__start___verbose"); + error = dlerror(); + if (error) { + goto done; + } + + stop = dlsym(handle, "__stop___verbose"); + error = dlerror(); + if (error) { + goto done; + + } else { + qb_log_callsites_register(start, stop); + } +done: + dlclose(handle); + } + + return 0; +} + void qb_log_init(const char *name, int32_t facility, int32_t priority) { int32_t i; @@ -331,7 +381,9 @@ void qb_log_init(const char *name, int32_t facility, int32_t priority) } conf[QB_LOG_SYSLOG].state = QB_LOG_STATE_ENABLED; qb_list_add(&conf[QB_LOG_SYSLOG].active_list, &active_targets); + qb_log_callsites_register(__start___verbose, __stop___verbose); + dl_iterate_phdr(_log_so_walk_callback, NULL); conf[QB_LOG_STDERR].state = QB_LOG_STATE_DISABLED; conf[QB_LOG_BLACKBOX].state = QB_LOG_STATE_DISABLED;