update_heap_memory_size(true, 0);
}
- lsan_open_liblsan();
+ lsan_init();
process_features();
PRINTMSG("dynamic analyzer probe helper so loading... pid[%d]\n",
{
int i;
- lsan_close_liblsan();
+ lsan_uninit();
cleanup_binaries();
gTraceInfo.init_complete = -1;
#include <stdio.h>
#include <string.h>
#include <ulimit.h>
+#include <assert.h>
#include "lsan_open.h"
#include "binproto.h"
#include "daprobe.h"
#include "file_buffer.h"
#include "lsan/lsan_interface.h"
+
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
+
+
static void *liblsan_handle;
int lsan_init_succeeded;
typedef struct LeakedObject LeakedObject;
+static const char *const sym_name_table[] = {
+ /* libc interceptors */
+ "__interceptor_malloc",
+ "__interceptor_calloc",
+ "__interceptor_realloc",
+ "__interceptor_free",
+ "__interceptor_posix_memalign",
+ "__interceptor_strdup",
+
+ /* pthread interceptors */
+ "__interceptor_pthread_create",
+ "__interceptor_pthread_join",
+};
+
+static_assert(LSAN_SID_CNT == ARRAY_SIZE(sym_name_table),
+ "LSan: Incorrect table of symbol names");
+
+static void *sym_table[LSAN_SID_CNT];
+
+static bool sym_table_init(void *lsan_handle)
+{
+ for (size_t i = 0; i < ARRAY_SIZE(sym_table); ++i) {
+ const char *sym_name = sym_name_table[i];
+ void *addr = dlsym(lsan_handle, sym_name);
+ if (addr) {
+ PRINTMSG("Loaded LSan symbol %s at address %p",
+ sym_name, addr);
+ } else {
+ PRINTERR("Cannot found LSan symbol: %s", sym_name);
+ return false;
+ }
+
+ sym_table[i] = addr;
+ }
+
+ return true;
+}
+
+static void sym_table_uninit()
+{
+ for (size_t i = 0; i < ARRAY_SIZE(sym_table); ++i)
+ sym_table[i] = NULL;
+}
+
+void *lsan_sym(enum lsan_sym_id id)
+{
+ unsigned int idx = id;
+
+ if (idx < ARRAY_SIZE(sym_table))
+ return sym_table[idx];
+
+ PRINTERR("LSan: Incorrect sym_id: %u", idx);
+ return NULL;
+}
+
+
static size_t pack_report_msg(char *p, const char *path, size_t *path_offset)
{
char *msg_buf = p;
return report_file_name;
}
-int lsan_open_liblsan()
+bool lsan_init()
{
if (!isOptionEnabled(FL_LSAN, 0))
- return 0;
+ return false;
if (!isOptionEnabled(FL_MEMORY_ALLOC_ALWAYS_PROBING, 0)) {
PRINTERR("lsan cannot operate "
"with disabled alloc always feature");
- return 0;
+ return false;
}
liblsan_handle = dlopen(PROBELIB_LSAN, RTLD_NOW);
- if (liblsan_handle != NULL) {
- lsan_init_succeeded = 1;
- send_msg_to_host("da_swap_lsan.so init done!\n",
- LSAN_MSG_STATUS | LSAN_INIT_DONE);
- } else {
- PRINTERR("Cannot open da_swap_lsan.so due to reason: %s!\n",
- dlerror());
+ if (liblsan_handle == NULL) {
+ PRINTERR("Cannot dlopen due to reason: %s!",
+ PROBELIB_LSAN, dlerror());
+ return false;
+ }
+
+ bool ret = sym_table_init(liblsan_handle);
+ if (!ret) {
+ dlclose(liblsan_handle);
+ liblsan_handle = NULL;
}
- return liblsan_handle != NULL;
+
+ lsan_init_succeeded = 1;
+ send_msg_to_host("da_swap_lsan.so init done!\n",
+ LSAN_MSG_STATUS | LSAN_INIT_DONE);
+
+ return true;
}
-void lsan_close_liblsan()
+void lsan_uninit()
{
- if (liblsan_handle)
+ if (liblsan_handle) {
+ sym_table_uninit();
dlclose(liblsan_handle);
+ }
}
static int lsan_call_int_cb(const char *func_name)
#ifdef __cplusplus
extern "C" {
+#else
+# include <stdbool.h>
#endif
+enum lsan_sym_id {
+ /* libc symbols ID */
+ LSAN_SID_MALLOC,
+ LSAN_SID_CALLOC,
+ LSAN_SID_REALLOC,
+ LSAN_SID_FREE,
+ LSAN_SID_POSIX_MEMALIGN,
+ LSAN_SID_STRDUP,
+
+ /* pthread symbols ID */
+ LSAN_SID_PTHREAD_CREATE,
+ LSAN_SID_PTHREAD_JOIN,
+
+ /* number of symbols */
+ LSAN_SID_CNT
+};
+
extern int lsan_init_succeeded;
-int lsan_open_liblsan();
-void lsan_close_liblsan();
-void *lsan_get_sym(const char *symbol_name);
+bool lsan_init();
+void lsan_uninit();
+void *lsan_sym(enum lsan_sym_id id);
void lsan_do_leak_check();
+/* TODO: Deprecated function, remove it. */
+void *lsan_get_sym(const char *symbol_name);
+
#ifdef __cplusplus
}
#endif
#include "probe_memory.h"
#include "lsan_open.h"
-/* TODO Split LSan */
-enum mem_symid {
- MEM_MALLOC,
- MEM_CALLOC,
- MEM_REALLOC,
- MEM_FREE,
- MEM_POSIX_MEMALIGN,
- MEM_STRDUP
-};
-
-/* TODO Split LSan */
-static const char *const real_functions[] = {
- "malloc",
- "calloc",
- "realloc",
- "free",
- "posix_memalign",
- "strdup"
-};
-
-/* TODO Split LSan */
-static const char *const lsan_interceptors[] = {
- "__interceptor_malloc",
- "__interceptor_calloc",
- "__interceptor_realloc",
- "__interceptor_free",
- "__interceptor_posix_memalign",
- "__interceptor_strdup"
-};
-
-
HANDLER_WRAPPERS(memory_feature, void *, malloc, size_t, size)
{
void *pret;
if (lsan_init_succeeded && lsan_mallocp == NULL)
- lsan_mallocp = lsan_get_sym(lsan_interceptors[MEM_MALLOC]);
+ lsan_mallocp = lsan_sym(LSAN_SID_MALLOC);
/* If LSan is used - call LSan allocator instead of origin */
mallocp = lsan_init_succeeded ? lsan_mallocp :
DECLARE_VARIABLE_STANDARD;
if (lsan_init_succeeded && lsan_freep == NULL)
- lsan_freep = lsan_get_sym(lsan_interceptors[MEM_FREE]);
+ lsan_freep = lsan_sym(LSAN_SID_FREE);
/* If LSan is used - call LSan free instead of origin */
freep = lsan_init_succeeded ? lsan_freep :
void *pret;
if (lsan_init_succeeded && lsan_reallocp == NULL)
- lsan_reallocp = lsan_get_sym(lsan_interceptors[MEM_REALLOC]);
+ lsan_reallocp = lsan_sym(LSAN_SID_REALLOC);
/* If LSan is used - call LSan realloc instead of origin */
reallocp = lsan_init_succeeded ? lsan_reallocp :
// }
if (lsan_init_succeeded && lsan_callocp == NULL)
- lsan_callocp = lsan_get_sym(lsan_interceptors[MEM_CALLOC]);
+ lsan_callocp = lsan_sym(LSAN_SID_CALLOC);
/* If LSan is used - call LSan calloc instead of origin */
callocp = lsan_init_succeeded ? lsan_callocp :
int iret;
if (lsan_init_succeeded && lsan_posix_memalignp == NULL)
- lsan_posix_memalignp = lsan_get_sym(
- lsan_interceptors[MEM_POSIX_MEMALIGN]);
+ lsan_posix_memalignp = lsan_sym(LSAN_SID_POSIX_MEMALIGN);
/* If LSan is used - call LSan calloc instead of origin */
posix_memalignp = lsan_init_succeeded ?
int size = strlen(s);
if (lsan_init_succeeded && lsan_strdupp == NULL)
- lsan_strdupp = lsan_get_sym(lsan_interceptors[MEM_STRDUP]);
+ lsan_strdupp = lsan_sym(LSAN_SID_STRDUP);
/* If LSan is used - call LSan strdup instead of origin */
strdupp = lsan_init_succeeded ? lsan_strdupp :
void _da_cleanup_handler(void *data);
void *_da_ThreadProc(void *params);
-/* TODO Split LSan */
-const char lsan_pthread_create[] = "__interceptor_pthread_create";
-const char lsan_pthread_join[] = "__interceptor_pthread_join";
/* Typedef to make HANDLER_WRAPPERS macro work with func pointer */
typedef void *(*start_routine_t)(void *);
DECLARE_VARIABLE_STANDARD;
if (lsan_init_succeeded && lsan_pthread_createp == NULL)
- lsan_pthread_createp = lsan_get_sym(lsan_pthread_create);
+ lsan_pthread_createp = lsan_sym(LSAN_SID_PTHREAD_CREATE);
pthread_createp = lsan_init_succeeded ? lsan_pthread_createp :
(void *)PROBE_GET_FUNC(probe_data);
DECLARE_VARIABLE_STANDARD;
if (lsan_init_succeeded && lsan_pthread_joinp == NULL)
- lsan_pthread_joinp = lsan_get_sym(lsan_pthread_join);
+ lsan_pthread_joinp = lsan_sym(LSAN_SID_PTHREAD_JOIN);
pthread_joinp = lsan_init_succeeded ? lsan_pthread_joinp :
(void *)PROBE_GET_FUNC(probe_data);