clouseau/src/lib/clouseau_preload.c

148 lines
3.5 KiB
C

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <dlfcn.h>
#include <execinfo.h>
#include "Clouseau.h"
static Eina_Bool _elm_is_init = EINA_FALSE;
static const char *_my_app_name = NULL;
/** PRELOAD functions. */
/* Hook on the elm_init
* We only do something here if we didn't already go into elm_init,
* which probably means we are not using elm. */
EAPI int
elm_init(int argc, char **argv)
{
int (*_elm_init)(int, char **) = dlsym(RTLD_NEXT, __func__);
setenv("ELM_CLOUSEAU", "0", 1);
if (!_elm_is_init)
{
_my_app_name = argv[0];
_elm_is_init = EINA_TRUE;
}
return _elm_init(argc, argv);
}
/* Hook on the main loop
* We only do something here if we didn't already go into elm_init,
* which probably means we are not using elm. */
EAPI void
ecore_main_loop_begin(void)
{
void (*_ecore_main_loop_begin)(void) = dlsym(RTLD_NEXT, __func__);
if (!_elm_is_init)
{
_my_app_name = "unknown";
}
clouseau_init();
if(!clouseau_app_connect(_my_app_name))
{
printf("Failed to connect to server.\n");
return;
}
_ecore_main_loop_begin();
clouseau_shutdown();
return;
}
#define EINA_LOCK_DEBUG_BT_NUM 64
static void
_clouseau_efl_object_dbg_info_get(Eo *obj, void *pd EINA_UNUSED, Efl_Dbg_Info *root)
{
const char *bt;
Efl_Dbg_Info *creation;
bt = efl_key_data_get(obj, ".clouseau.bt");
creation = EFL_DBG_INFO_LIST_APPEND(root, "Creation");
EFL_DBG_INFO_APPEND(creation, "Backtrace", EINA_VALUE_TYPE_STRING, bt);
efl_dbg_info_get(efl_super(obj, EFL_OBJECT_OVERRIDE_CLASS), root);
}
static void
_clouseau_efl_destructor(Eo *obj, void *pd EINA_UNUSED)
{
char *bt;
bt = efl_key_data_get(obj, ".clouseau.bt");
free(bt);
efl_destructor(efl_super(obj, EFL_OBJECT_OVERRIDE_CLASS));
}
static char*
_clouseau_backtrace_create(void)
{
void *bt[EINA_LOCK_DEBUG_BT_NUM];
Eina_Strbuf *buf;
int lock_bt_num;
lock_bt_num = backtrace((void **)bt, EINA_LOCK_DEBUG_BT_NUM);
buf = eina_strbuf_new();
for (int i = 0; i < lock_bt_num; ++i)
{
Dl_info info;
const char *file;
unsigned long long offset, base;
if ((dladdr(bt[i], &info)) && (info.dli_fname[0]))
{
offset = (unsigned long long)bt[i];
base = (unsigned long long)info.dli_fbase;
file = info.dli_fname;
}
if (file)
eina_strbuf_append_printf(buf, "%s\t 0x%llx 0x%llx\n", file, offset, base);
else
eina_strbuf_append_printf(buf, "??\t -\n");
}
{
char *str;
str = eina_strbuf_string_steal(buf);
eina_strbuf_free(buf);
return str;
}
}
EAPI Eo*
_efl_add_internal_start(const char *file, int line, const Efl_Class *klass_id, Eo *parent_id, Eina_Bool ref, Eina_Bool is_fallback)
{
Eo* (*__efl_add_internal_start)(const char *file, int line, const Efl_Class *klass_id, Eo *parent_id, Eina_Bool ref EINA_UNUSED, Eina_Bool is_fallback);
const char *str;
Eo *obj;
//create bt
str = _clouseau_backtrace_create();
//containue construction
__efl_add_internal_start = dlsym(RTLD_NEXT, __func__);
obj = __efl_add_internal_start(file, line, klass_id, parent_id, ref, is_fallback);
//override needed functions
EFL_OPS_DEFINE(ops,
EFL_OBJECT_OP_FUNC(efl_dbg_info_get, _clouseau_efl_object_dbg_info_get),
EFL_OBJECT_OP_FUNC(efl_destructor, _clouseau_efl_destructor)
);
efl_object_override(obj, &ops);
//add backtrace and free buf
efl_key_data_set(obj, ".clouseau.bt", str);
return obj;
}