*/
-#ifdef PRELOAD_ACTIVATE
+#ifdef PRELOAD_ACTIVATE
#include <dlfcn.h>
#define PRELOAD_FILE SHARE_PREFIX"/preload_list.txt"
#define PRELOAD_FILE_WRT SHARE_PREFIX"/preload_list_wrt.txt"
-#define EFL_PREINIT_FUNC "elm_quicklaunch_init"
-#define EFL_SHUTDOWN_FUNC "elm_quicklaunch_shutdown"
+#define EFL_PREINIT_FUNC "elm_quicklaunch_init"
+#define EFL_SHUTDOWN_FUNC "elm_quicklaunch_shutdown"
static int preload_initialized = 0;
static int g_argc;
static inline void __preload_init(int argc, char **argv)
{
- void *handle = NULL;
- char soname[MAX_LOCAL_BUFSZ] = {0, };
- FILE *preload_list;
- int (*func)() = NULL;
- int i;
-
- g_argc = argc;
- g_argv = argv;
- for (i = 0; i < argc; i++) {
- max_cmdline_size += (strlen(argv[i]) + 1);
- }
- _D("max_cmdline_size = %d", max_cmdline_size);
-
- preload_list = fopen(PRELOAD_FILE, "rt");
- if (preload_list == NULL) {
- _E("no preload\n");
- return;
- }
-
- while (fgets(soname, MAX_LOCAL_BUFSZ, preload_list) > (char*)0) {
- soname[MAX_LOCAL_BUFSZ-1] = 0;
- handle = dlopen(soname, RTLD_NOW);
- if (handle == NULL)
- continue;
- _D("preload %s# - handle : %x\n", soname, handle);
-
- func = dlsym(handle, EFL_PREINIT_FUNC);
- if (func != NULL) {
- _D("get pre-initialization function\n");
- dl_einit = func;
- func = dlsym(handle, EFL_SHUTDOWN_FUNC);
- if (func != NULL) {
- _D("get shutdown function\n");
- dl_efini = func;
- }
- }
- }
-
- fclose(preload_list);
- preload_initialized = 1;
+ void *handle = NULL;
+ char soname[MAX_LOCAL_BUFSZ] = {0, };
+ FILE *preload_list;
+ int (*func)() = NULL;
+ int i;
+
+ g_argc = argc;
+ g_argv = argv;
+ for (i = 0; i < argc; i++) {
+ max_cmdline_size += (strlen(argv[i]) + 1);
+ }
+ _D("max_cmdline_size = %d", max_cmdline_size);
+
+ preload_list = fopen(PRELOAD_FILE, "rt");
+ if (preload_list == NULL) {
+ _E("no preload\n");
+ return;
+ }
+
+ while (fgets(soname, MAX_LOCAL_BUFSZ, preload_list) > (char*)0) {
+ soname[MAX_LOCAL_BUFSZ-1] = 0;
+ handle = dlopen(soname, RTLD_NOW);
+ if (handle == NULL)
+ continue;
+ _D("preload %s# - handle : %x\n", soname, handle);
+
+ func = dlsym(handle, EFL_PREINIT_FUNC);
+ if (func != NULL) {
+ _D("get pre-initialization function\n");
+ dl_einit = func;
+ func = dlsym(handle, EFL_SHUTDOWN_FUNC);
+ if (func != NULL) {
+ _D("get shutdown function\n");
+ dl_efini = func;
+ }
+ }
+ }
+
+ fclose(preload_list);
+ preload_initialized = 1;
}
static inline int preinit_init()
{
- if (dl_einit != NULL)
- dl_einit(0, NULL);
- _D("pre-initialzation on");
- return 0;
+ if (dl_einit != NULL)
+ dl_einit(0, NULL);
+ _D("pre-initialzation on");
+ return 0;
}
static inline int preinit_fini()
{
- if (dl_efini != NULL)
- dl_efini();
- _D("pre-initialization off");
- return 0;
+ if (dl_efini != NULL)
+ dl_efini();
+ _D("pre-initialization off");
+ return 0;
}
/* TODO : how to set cmdline gracefully ?? */
static inline int __change_cmdline(char *cmdline)
{
- if (strlen(cmdline) > max_cmdline_size + 1) {
- _E("cmdline exceed max size : %d", max_cmdline_size);
- return -1;
- }
+ if (strlen(cmdline) > max_cmdline_size + 1) {
+ _E("cmdline exceed max size : %d", max_cmdline_size);
+ return -1;
+ }
- memset(g_argv[0], '\0', max_cmdline_size);
- snprintf(g_argv[0], max_cmdline_size, "%s", cmdline);
+ memset(g_argv[0], '\0', max_cmdline_size);
+ snprintf(g_argv[0], max_cmdline_size, "%s", cmdline);
- return 0;
+ return 0;
}
static inline void __preload_exec(int argc, char **argv)
{
- void *handle = NULL;
- int (*dl_main) (int, char **);
+ void *handle = NULL;
+ int (*dl_main) (int, char **);
- if (!preload_initialized)
- return;
+ if (!preload_initialized)
+ return;
- handle = dlopen(argv[0], RTLD_LAZY | RTLD_GLOBAL);
- if (handle == NULL) {
- return;
- }
+ handle = dlopen(argv[0], RTLD_LAZY | RTLD_GLOBAL);
+ if (handle == NULL) {
+ return;
+ }
- dl_main = dlsym(handle, "main");
- if (dl_main != NULL) {
+ dl_main = dlsym(handle, "main");
+ if (dl_main != NULL) {
#ifndef NATIVE_LAUNCHPAD
/* do nothing */
#else
- if (__change_cmdline(argv[0]) < 0) {
- _E("change cmdline fail");
- return;
- }
+ if (__change_cmdline(argv[0]) < 0) {
+ _E("change cmdline fail");
+ return;
+ }
#endif
- dl_main(argc, argv);
- } else {
- _E("dlsym not founded. bad preloaded app - check fpie pie");
- }
+ dl_main(argc, argv);
+ } else {
+ _E("dlsym not founded. bad preloaded app - check fpie pie");
+ }
- exit(0);
+ exit(0);
+}
+
+static int g_dlopen_size = 5;
+static int g_dlopen_count = 0;
+static void** g_dlopen_handle_list = NULL;
+
+static inline int __preload_save_dlopen_handle(void *handle)
+{
+ if (!handle) {
+ return 1;
+ }
+ if (g_dlopen_count == g_dlopen_size || !g_dlopen_handle_list) {
+ void** tmp = realloc(g_dlopen_handle_list, 2 * g_dlopen_size * sizeof(void *));
+ if (NULL == tmp) {
+ _E("out of memory\n");
+ dlclose(handle);
+ return 1;
+ }
+ g_dlopen_size *= 2;
+ g_dlopen_handle_list = tmp;
+ }
+ g_dlopen_handle_list[g_dlopen_count++] = handle;
+ return 0;
+}
+
+static inline void __preload_fini_for_wrt()
+{
+ int i = 0;
+ if (!g_dlopen_handle_list)
+ return;
+ for (i = 0; i < g_dlopen_count; ++i)
+ {
+ void *handle = g_dlopen_handle_list[i];
+ if (handle) {
+ if (0 != dlclose(handle)) {
+ _E("dlclose failed\n");
+ }
+ }
+ }
+ free(g_dlopen_handle_list);
+ g_dlopen_handle_list = NULL;
+ g_dlopen_size = 5;
+ g_dlopen_count = 0;
}
static inline void __preload_init_for_wrt()
{
- void *handle = NULL;
- char soname[MAX_LOCAL_BUFSZ];
- FILE *preload_list;
-
- preload_list = fopen(PRELOAD_FILE_WRT, "rt");
- if (preload_list == NULL) {
- _E("no wrt preload\n");
- return;
- }
-
- while (fgets(soname, MAX_LOCAL_BUFSZ, preload_list) > (char*)0) {
- soname[strlen(soname) - 1] = 0;
- handle = dlopen((const char *)soname, RTLD_NOW|RTLD_GLOBAL);
- if (handle == NULL)
- continue;
- _D("preload %s# - handle : %x\n", soname, handle);
- }
-
- fclose(preload_list);
+ if (0 != atexit(__preload_fini_for_wrt)) {
+ _E("Cannot register atexit callback. Libraries will not be unloaded");
+ }
+ void *handle = NULL;
+ char soname[MAX_LOCAL_BUFSZ];
+ FILE *preload_list;
+
+ preload_list = fopen(PRELOAD_FILE_WRT, "rt");
+ if (preload_list == NULL) {
+ _E("no wrt preload\n");
+ return;
+ }
+
+ while (fgets(soname, MAX_LOCAL_BUFSZ, preload_list) != NULL) {
+ size_t len = strnlen(soname, MAX_LOCAL_BUFSZ);
+ if (len > 0)
+ soname[len - 1] = '\0';
+ handle = dlopen(soname, RTLD_NOW|RTLD_GLOBAL);
+ if (handle == NULL)
+ continue;
+ if (0 != __preload_save_dlopen_handle(handle)) {
+ _E("Cannot save handle, no more preloads");
+ break;
+ }
+ _D("preload %s# - handle : %x\n", soname, handle);
+ }
+
+ fclose(preload_list);
}
#else