summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xCMakeLists.txt4
-rw-r--r--inc/debugger_info.h33
-rw-r--r--inc/key.h44
-rw-r--r--inc/launchpad_debug.h31
-rw-r--r--packaging/default.debugger.in20
-rw-r--r--packaging/launchpad.spec3
-rw-r--r--src/debugger_info.c295
-rwxr-xr-xsrc/launchpad.c165
-rw-r--r--src/launchpad_debug.c308
9 files changed, 850 insertions, 53 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 28ad574..2c0aa51 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -99,6 +99,8 @@ SET(${LAUNCHPAD_PROCESS_POOL}_SOURCE_FILES
src/launchpad_common.c
src/loader_info.c
src/launcher_info.c
+ src/debugger_info.c
+ src/launchpad_debug.c
)
ADD_EXECUTABLE(${LAUNCHPAD_PROCESS_POOL} ${${LAUNCHPAD_PROCESS_POOL}_SOURCE_FILES})
@@ -108,6 +110,8 @@ SET_TARGET_PROPERTIES(${LAUNCHPAD_PROCESS_POOL}
PROPERTIES SKIP_BUILD_RPATH TRUE
) # remove rpath option that is automatically generated by cmake.
+CONFIGURE_FILE(packaging/default.debugger.in packaging/default.debugger @ONLY)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/packaging/default.debugger DESTINATION share/aul)
INSTALL(TARGETS ${LAUNCHPAD_PROCESS_POOL} DESTINATION bin)
CONFIGURE_FILE(packaging/default.loader.in packaging/default.loader @ONLY)
diff --git a/inc/debugger_info.h b/inc/debugger_info.h
new file mode 100644
index 0000000..7f61846
--- /dev/null
+++ b/inc/debugger_info.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __DEBUGGER_INFO_H__
+#define __DEBUGGER_INFO_H__
+
+#include <glib.h>
+
+typedef struct debugger_info_s *debugger_info_h;
+
+GList *_debugger_info_load(const char *path);
+void _debugger_info_unload(GList *info);
+debugger_info_h _debugger_info_find(GList *info_list, const char *name);
+const char *_debugger_info_get_exe(debugger_info_h info);
+GList *_debugger_info_get_extra_key_list(debugger_info_h info);
+GList *_debugger_info_get_extra_env_list(debugger_info_h info);
+GList *_debugger_info_get_unlink_list(debugger_info_h info);
+const char *_debugger_info_get_attach(debugger_info_h info);
+
+#endif /* __DEBUGGER_INFO_H__ */
diff --git a/inc/key.h b/inc/key.h
index 7d0201f..e83bb14 100644
--- a/inc/key.h
+++ b/inc/key.h
@@ -21,28 +21,30 @@
extern "C" {
#endif
-#define AUL_K_STARTTIME "__AUL_STARTTIME__"
-#define AUL_K_EXEC "__AUL_EXEC__"
-#define AUL_K_PACKAGETYPE "__AUL_PACKAGETYPE__"
-#define AUL_K_APP_TYPE "__AUL_APP_TYPE__"
-#define AUL_K_HWACC "__AUL_HWACC__"
-#define AUL_K_APPID "__AUL_APPID__"
-#define AUL_K_PID "__AUL_PID__"
-#define AUL_K_TASKMANAGE "__AUL_TASKMANAGE__"
-#define AUL_K_INTERNAL_POOL "__AUL_INTERNAL_POOL__"
-#define AUL_K_PKGID "__AUL_PKGID_"
-#define AUL_K_DEBUG "__AUL_DEBUG__"
+#define AUL_K_STARTTIME "__AUL_STARTTIME__"
+#define AUL_K_EXEC "__AUL_EXEC__"
+#define AUL_K_PACKAGETYPE "__AUL_PACKAGETYPE__"
+#define AUL_K_APP_TYPE "__AUL_APP_TYPE__"
+#define AUL_K_HWACC "__AUL_HWACC__"
+#define AUL_K_APPID "__AUL_APPID__"
+#define AUL_K_PID "__AUL_PID__"
+#define AUL_K_TASKMANAGE "__AUL_TASKMANAGE__"
+#define AUL_K_INTERNAL_POOL "__AUL_INTERNAL_POOL__"
+#define AUL_K_PKGID "__AUL_PKGID_"
+#define AUL_K_DEBUG "__AUL_DEBUG__"
#define AUL_K_PRIVACY_APPID "__AUL_PRIVACY_APPID__"
-#define AUL_K_COMP_TYPE "__AUL_COMP_TYPE__"
-#define AUL_K_CALLER_PID "__AUL_CALLER_PID__"
-#define AUL_K_LOADER_ID "__AUL_LOADER_ID__"
-#define AUL_K_LOADER_PATH "__AUL_LOADER_PATH__"
-#define AUL_K_LOADER_EXTRA "__AUL_LOADER_EXTRA__"
-#define AUL_K_WAYLAND_DISPLAY "__AUL_WAYLAND_DISPLAY__"
-#define AUL_K_WAYLAND_WORKING_DIR "__AUL_WAYLAND_WORKING_DIR__"
-#define AUL_K_ROOT_PATH "__AUL_ROOT_PATH__"
-#define AUL_K_API_VERSION "__AUL_API_VERSION__"
-#define AUL_K_LOADER_NAME "__AUL_LOADER_NAME__"
+#define AUL_K_COMP_TYPE "__AUL_COMP_TYPE__"
+#define AUL_K_CALLER_PID "__AUL_CALLER_PID__"
+#define AUL_K_LOADER_ID "__AUL_LOADER_ID__"
+#define AUL_K_LOADER_PATH "__AUL_LOADER_PATH__"
+#define AUL_K_LOADER_EXTRA "__AUL_LOADER_EXTRA__"
+#define AUL_K_WAYLAND_DISPLAY "__AUL_WAYLAND_DISPLAY__"
+#define AUL_K_WAYLAND_WORKING_DIR "__AUL_WAYLAND_WORKING_DIR__"
+#define AUL_K_ROOT_PATH "__AUL_ROOT_PATH__"
+#define AUL_K_API_VERSION "__AUL_API_VERSION__"
+#define AUL_K_LOADER_NAME "__AUL_LOADER_NAME__"
+#define AUL_K_SDK "__AUL_SDK__"
+#define AUL_K_ORG_CALLER_PID "__AUL_ORG_CALLER_PID__"
#ifdef __cplusplus
}
diff --git a/inc/launchpad_debug.h b/inc/launchpad_debug.h
new file mode 100644
index 0000000..8bdb6ef
--- /dev/null
+++ b/inc/launchpad_debug.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LAUNCHPAD_DEBUG_H__
+#define __LAUNCHPAD_DEBUG_H__
+
+#include <stdbool.h>
+#include <bundle.h>
+
+int _debug_create_argv(int *argc, char ***argv, bool *attach);
+void _debug_destroy_argv(int argc, char **argv);
+int _debug_get_caller_pid(bundle *kb);
+void _debug_prepare_debugger(bundle *kb);
+int _debug_init(void);
+void _debug_fini(void);
+
+#endif /* __LAUNCHPAD_DEBUG_H__ */
+
diff --git a/packaging/default.debugger.in b/packaging/default.debugger.in
new file mode 100644
index 0000000..ee2e717
--- /dev/null
+++ b/packaging/default.debugger.in
@@ -0,0 +1,20 @@
+[DEBUGGER]
+NAME VALGRIND
+EXE /opt/usr/home/owner/share/tmp/sdk_tools/valgrind/usr/bin/valgrind
+APP_TYPE capp|c++app
+EXTRA_KEY __DLP_VALGRIND_ARG__
+UNLINK /tmp/valgrind_result.txt
+UNLINK /tmp/valgrind_result.xml
+
+[DEBUGGER]
+NAME DEBUG
+EXE /opt/usr/home/owner/share/tmp/sdk_tools/gdbserver/gdbserver
+APP_TYPE capp|c++app
+EXTRA_KEY __DLP_DEBUG_ARG__
+
+[DEBUGGER]
+NAME ATTACH
+EXE /opt/usr/home/owner/share/tmp/sdk_tools/gdbserver/gdbserver
+APP_TYPE capp|c++app
+EXTRA_KEY __DLP_ATTACH_ARG__
+ATTACH true
diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec
index d11ed9d..06b6eb3 100644
--- a/packaging/launchpad.spec
+++ b/packaging/launchpad.spec
@@ -79,11 +79,12 @@ cp %{_builddir}/%{name}-%{version}/LICENSE %{buildroot}/usr/share/license/%{nam
%manifest launchpad.manifest
%{_prefix}/share/license/%{name}
%{_prefix}/share/aul/default.loader
+%{_prefix}/share/aul/default.debugger
%{_unitdir_user}/launchpad-process-pool.service
%{_unitdir_user}/launchpad-process-pool.socket
%{_unitdir_user}/sockets.target.wants/launchpad-process-pool.socket
%{_unitdir_user}/basic.target.wants/launchpad-process-pool.service
-%caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/launchpad-process-pool
+%caps(cap_mac_admin,cap_dac_override,cap_setgid=ei) %{_bindir}/launchpad-process-pool
%caps(cap_setgid=ei) %{_bindir}/launchpad-loader
%attr(0644,root,root) %{_libdir}/liblaunchpad.so.*
diff --git a/src/debugger_info.c b/src/debugger_info.c
new file mode 100644
index 0000000..4af4a2d
--- /dev/null
+++ b/src/debugger_info.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "launchpad_common.h"
+#include "debugger_info.h"
+
+#define TAG_DEBUGGER "[DEBUGGER]"
+#define TAG_NAME "NAME"
+#define TAG_EXE "EXE"
+#define TAG_APP_TYPE "APP_TYPE"
+#define TAG_EXTRA_KEY "EXTRA_KEY"
+#define TAG_EXTRA_ENV "EXTRA_ENV"
+#define TAG_UNLINK "UNLINK"
+#define TAG_ATTACH "ATTACH"
+
+struct debugger_info_s {
+ char *name;
+ char *exe;
+ GList *app_types;
+ GList *extra_key_list;
+ GList *extra_env_list;
+ GList *unlink_list;
+ char *attach;
+};
+
+static struct debugger_info_s *__create_debugger_info(void)
+{
+ struct debugger_info_s *info;
+
+ info = calloc(1, sizeof(struct debugger_info_s));
+ if (info == NULL) {
+ _E("out of memory");
+ return NULL;
+ }
+
+ return info;
+}
+
+static void __destroy_debugger_info(gpointer data)
+{
+ struct debugger_info_s *info = (struct debugger_info_s *)data;
+
+ if (info == NULL)
+ return;
+
+ if (info->attach)
+ free(info->attach);
+ if (info->unlink_list)
+ g_list_free_full(info->unlink_list, free);
+ if (info->extra_env_list)
+ g_list_free_full(info->extra_env_list, free);
+ if (info->extra_key_list)
+ g_list_free_full(info->extra_key_list, free);
+ if (info->app_types)
+ g_list_free_full(info->app_types, free);
+ if (info->exe)
+ free(info->exe);
+ if (info->name)
+ free(info->name);
+ free(info);
+}
+
+static void __parse_app_types(struct debugger_info_s *info, char *line)
+{
+ char *token;
+ char *saveptr = NULL;
+ char tok[LINE_MAX];
+
+ token = strtok_r(line, "|", &saveptr);
+ while (token) {
+ tok[0] = '\0';
+ sscanf(token, "%s", tok);
+ if (tok[0] != '\0' && strcasecmp(tok, "null") != 0) {
+ info->app_types = g_list_append(info->app_types,
+ strdup(tok));
+ }
+ token = strtok_r(NULL, "|", &saveptr);
+ }
+}
+
+static GList *__parse_file(GList *list, const char *path)
+{
+ FILE *fp;
+ char buf[LINE_MAX];
+ char tok1[LINE_MAX];
+ char tok2[LINE_MAX];
+ struct debugger_info_s *info = NULL;
+
+ fp = fopen(path, "rt");
+ if (fp == NULL)
+ return list;
+
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ tok1[0] = '\0';
+ tok2[0] = '\0';
+ sscanf(buf, "%s %s", tok1, tok2);
+
+ if (strcasecmp(TAG_DEBUGGER, tok1) == 0) {
+ if (info) {
+ _D("name: %s, exe: %s", info->name, info->exe);
+ list = g_list_append(list, info);
+ }
+
+ info = __create_debugger_info();
+ if (info == NULL)
+ break;
+
+ continue;
+ }
+
+ if (tok1[0] == '\0' || tok2[0] == '\0' || tok1[0] == '#')
+ continue;
+ if (info == NULL)
+ continue;
+
+ if (strcasecmp(TAG_NAME, tok1) == 0) {
+ info->name = strdup(tok2);
+ if (info->name == NULL) {
+ _E("out of memory");
+ __destroy_debugger_info(info);
+ info = NULL;
+ break;
+ }
+ } else if (strcasecmp(TAG_EXE, tok1) == 0) {
+ info->exe = strdup(tok2);
+ if (info->exe == NULL) {
+ _E("out of memory");
+ __destroy_debugger_info(info);
+ info = NULL;
+ break;
+ }
+ } else if (strcasecmp(TAG_APP_TYPE, tok1) == 0) {
+ __parse_app_types(info, &buf[strlen(tok1)]);
+ if (info->app_types == NULL) {
+ _E("app_types is NULL");
+ __destroy_debugger_info(info);
+ info = NULL;
+ break;
+ }
+ } else if (strcasecmp(TAG_EXTRA_KEY, tok1) == 0) {
+ info->extra_key_list = g_list_append(
+ info->extra_key_list, strdup(tok2));
+ } else if (strcasecmp(TAG_EXTRA_ENV, tok1) == 0) {
+ info->extra_env_list = g_list_append(
+ info->extra_env_list, strdup(tok2));
+ } else if (strcasecmp(TAG_UNLINK, tok1) == 0) {
+ info->unlink_list = g_list_append(info->unlink_list,
+ strdup(tok2));
+ } else if (strcasecmp(TAG_ATTACH, tok1) == 0) {
+ info->attach = strdup(tok2);
+ if (info->attach == NULL) {
+ _E("attach is NULL");
+ __destroy_debugger_info(info);
+ info = NULL;
+ break;
+ }
+ }
+ }
+ fclose(fp);
+
+ if (info) {
+ _D("name: %s, exe: %s", info->name, info->exe);
+ list = g_list_append(list, info);
+ }
+
+ return list;
+}
+
+GList *_debugger_info_load(const char *path)
+{
+ DIR *dp;
+ struct dirent dentry;
+ struct dirent *result = NULL;
+ GList *list = NULL;
+ char buf[PATH_MAX];
+ char *ext;
+
+ if (path == NULL)
+ return NULL;
+
+ dp = opendir(path);
+ if (dp == NULL)
+ return NULL;
+
+ while (readdir_r(dp, &dentry, &result) == 0 && result != NULL) {
+ if (dentry.d_name[0] == '.')
+ continue;
+
+ ext = strrchr(dentry.d_name, '.');
+ if (ext && strcmp(ext, ".debugger") == 0) {
+ snprintf(buf, sizeof(buf), "%s/%s",
+ path, dentry.d_name);
+ list = __parse_file(list, buf);
+ }
+ }
+ closedir(dp);
+
+ return list;
+}
+
+void _debugger_info_unload(GList *info)
+{
+ if (info == NULL)
+ return;
+
+ g_list_free_full(info, __destroy_debugger_info);
+}
+
+static int __comp_name(gconstpointer a, gconstpointer b)
+{
+ struct debugger_info_s *info = (struct debugger_info_s *)a;
+
+ if (info == NULL || info->name == NULL || b == NULL)
+ return -1;
+
+ if (strcasecmp(info->name, b) == 0)
+ return 0;
+
+ return -1;
+}
+
+debugger_info_h _debugger_info_find(GList *info_list, const char *name)
+{
+ GList *list;
+
+ if (info_list == NULL || name == NULL)
+ return NULL;
+
+ list = g_list_find_custom(info_list, name, __comp_name);
+ if (list == NULL)
+ return NULL;
+
+ return (debugger_info_h)list->data;
+}
+
+const char *_debugger_info_get_exe(debugger_info_h info)
+{
+ if (info == NULL)
+ return NULL;
+
+ return info->exe;
+}
+
+GList *_debugger_info_get_extra_key_list(debugger_info_h info)
+{
+ if (info == NULL)
+ return NULL;
+
+ return info->extra_key_list;
+}
+
+GList *_debugger_info_get_extra_env_list(debugger_info_h info)
+{
+ if (info == NULL)
+ return NULL;
+
+ return info->extra_env_list;
+}
+
+GList *_debugger_info_get_unlink_list(debugger_info_h info)
+{
+ if (info == NULL)
+ return NULL;
+
+ return info->unlink_list;
+}
+
+const char *_debugger_info_get_attach(debugger_info_h info)
+{
+ if (info == NULL)
+ return NULL;
+
+ return info->attach;
+}
diff --git a/src/launchpad.c b/src/launchpad.c
index 7917433..09e0431 100755
--- a/src/launchpad.c
+++ b/src/launchpad.c
@@ -42,6 +42,7 @@
#include "launchpad.h"
#include "loader_info.h"
#include "launcher_info.h"
+#include "launchpad_debug.h"
#define AUL_PR_NAME 16
#define EXEC_CANDIDATE_EXPIRED 5
@@ -91,6 +92,11 @@ struct app_launch_arg {
bundle *kb;
};
+struct app_arg {
+ int argc;
+ char **argv;
+};
+
static int __sys_hwacc;
static GList *loader_info_list;
static int user_slot_offset;
@@ -488,16 +494,17 @@ static int __send_launchpad_loader(candidate_process_context_t *cpc,
return pid;
}
-static int __normal_fork_exec(int argc, char **argv)
+static int __normal_fork_exec(int argc, char **argv, const char *app_path)
{
- char *libdir = NULL;
+ char *libdir;
_D("start real fork and exec");
- libdir = _get_libdir(argv[LOADER_ARG_PATH]);
- if (libdir)
+ libdir = _get_libdir(app_path);
+ if (libdir) {
setenv("LD_LIBRARY_PATH", libdir, 1);
- free(libdir);
+ free(libdir);
+ }
_close_all_fds();
if (execv(argv[LOADER_ARG_PATH], argv) < 0) { /* Flawfinder: ignore */
@@ -514,15 +521,14 @@ static int __normal_fork_exec(int argc, char **argv)
return 0;
}
-static int __set_launcher_info(int *argc, char ***argv, const char *app_type)
+static int __create_launcher_argv(int *argc, char ***argv, const char *app_type)
{
+ int launcher_argc;
+ char **launcher_argv;
launcher_info_h launcher_info;
- char **new_argv;
- int new_argc;
const char *exe;
- GList *extra_args;
- int extra_argc;
const char *extra_arg;
+ GList *extra_args;
GList *iter;
int i;
@@ -537,30 +543,111 @@ static int __set_launcher_info(int *argc, char ***argv, const char *app_type)
}
extra_args = _launcher_info_get_extra_args(launcher_info);
- extra_argc = g_list_length(extra_args) + 1;
-
- new_argc = *argc + extra_argc;
- new_argv = (char **)realloc(*argv, sizeof(char *) * new_argc);
- if (new_argv == NULL) {
- _E("Failed to reallocate memory");
+ launcher_argc = g_list_length(extra_args) + 1;
+ launcher_argv = (char **)calloc(launcher_argc, sizeof(char *));
+ if (launcher_argv == NULL) {
+ _E("out of memory");
return -1;
}
- for (i = new_argc; i >= extra_argc; i--)
- new_argv[i] = new_argv[i - extra_argc];
-
i = LOADER_ARG_PATH;
- new_argv[i++] = strdup(exe);
+ launcher_argv[i++] = strdup(exe);
iter = g_list_first(extra_args);
while (iter) {
- extra_arg = (char *)iter->data;
+ extra_arg = (const char *)iter->data;
if (extra_arg)
- new_argv[i++] = strdup(extra_arg);
+ launcher_argv[i++] = strdup(extra_arg);
iter = g_list_next(iter);
}
+ *argc = launcher_argc;
+ *argv = launcher_argv;
+
+
+ return 0;
+}
+
+static void __destroy_launcher_argv(int argc, char **argv)
+{
+ int i;
+
+ if (argv == NULL)
+ return;
+
+ for (i = 0; i < argc; i++)
+ free(argv[i]);
+ free(argv);
+}
+
+static int __create_app_argv(int *argc, char ***argv, const char *app_path,
+ bundle *kb, const char *app_type)
+{
+ int new_argc;
+ char **new_argv;
+ bool attach = false;
+ struct app_arg debug_arg = {0,};
+ struct app_arg launcher_arg = {0,};
+ struct app_arg arg = {0,};
+ int ret;
+ int i;
+ int c;
+
+ ret = _debug_create_argv(&debug_arg.argc, &debug_arg.argv, &attach);
+ if (ret < 0) {
+ _E("Failed to create debugger argv");
+ return -1;
+ }
+
+ if (attach) {
+ *argc = debug_arg.argc;
+ *argv = debug_arg.argv;
+ return 0;
+ }
+
+ ret = __create_launcher_argv(&launcher_arg.argc, &launcher_arg.argv,
+ app_type);
+ if (ret < 0) {
+ _E("Failed to create launcher argv");
+ _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
+ return -1;
+ }
+
+ arg.argc = bundle_export_to_argv(kb, &arg.argv);
+ if (arg.argc <= 0) {
+ _E("Failed to export bundle");
+ __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
+ _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
+ return -1;
+ }
+ arg.argv[LOADER_ARG_PATH] = strdup(app_path);
+
+ new_argc = debug_arg.argc + launcher_arg.argc + arg.argc;
+ if (new_argc == arg.argc) {
+ *argc = arg.argc;
+ *argv = arg.argv;
+ return 0;
+ }
+
+ new_argv = (char **)calloc(new_argc + 1, sizeof(char *));
+ if (new_argv == NULL) {
+ _E("out of memory");
+ free(arg.argv[LOADER_ARG_PATH]);
+ bundle_free_exported_argv(arg.argc, &arg.argv);
+ __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv);
+ _debug_destroy_argv(debug_arg.argc, debug_arg.argv);
+ return -1;
+ }
+
+ c = LOADER_ARG_PATH;
+ for (i = 0; i < debug_arg.argc; i++)
+ new_argv[c++] = debug_arg.argv[i];
+ for (i = 0; i < launcher_arg.argc; i++)
+ new_argv[c++] = launcher_arg.argv[i];
+ for (i = 0; i < arg.argc; i++)
+ new_argv[c++] = arg.argv[i];
+
*argc = new_argc;
*argv = new_argv;
@@ -570,7 +657,7 @@ static int __set_launcher_info(int *argc, char ***argv, const char *app_type)
static void __real_launch(const char *app_path, bundle *kb,
appinfo_t *menu_info)
{
- int app_argc;
+ int app_argc = 0;
char **app_argv;
int i;
int ret;
@@ -578,20 +665,18 @@ static void __real_launch(const char *app_path, bundle *kb,
if (bundle_get_val(kb, AUL_K_DEBUG) != NULL)
putenv("TIZEN_DEBUGGING_PORT=1");
- app_argv = _create_argc_argv(kb, &app_argc);
- app_argv[LOADER_ARG_PATH] = strdup(app_path);
-
- ret = __set_launcher_info(&app_argc, &app_argv, menu_info->app_type);
+ ret = __create_app_argv(&app_argc, &app_argv, app_path,
+ kb, menu_info->app_type);
if (ret < 0) {
- _E("Failed to set launcher info");
+ _E("Failed to create app argv");
exit(-1);
}
- for (i = 0; i < app_argc; i += 2)
+ for (i = 0; i < app_argc; i++)
SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
PERF("setup argument done");
- __normal_fork_exec(app_argc, app_argv);
+ __normal_fork_exec(app_argc, app_argv, app_path);
}
static int __prepare_exec(const char *appid, const char *app_path,
@@ -646,6 +731,9 @@ static int __exec_app_process(void *arg)
PERF("fork done");
_D("lock up test log(no error) : fork done");
+ if (bundle_get_type(launch_arg->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE)
+ _debug_prepare_debugger(launch_arg->kb);
+
__signal_unblock_sigchld();
__signal_fini();
@@ -1081,7 +1169,9 @@ static int __check_caller_by_pid(int pid)
if (ret < 0)
return -1;
- if (strcmp(buf, "User") == 0)
+ if (strcmp(buf, "User") == 0 ||
+ strcmp(buf, "System") == 0 ||
+ strcmp(buf, "System::Privileged") == 0)
return 0;
return -1;
@@ -1153,6 +1243,7 @@ static gboolean __handle_launch_event(gpointer data)
int type = -1;
int loader_id;
int ret;
+ int caller_pid;
traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "LAUNCHPAD:LAUNCH");
pkt = _recv_pkt_raw(fd, &clifd, &cr);
@@ -1174,6 +1265,17 @@ static gboolean __handle_launch_event(gpointer data)
goto end;
}
+ if (bundle_get_type(kb, AUL_K_SDK) != BUNDLE_TYPE_NONE) {
+ caller_pid = _debug_get_caller_pid(kb);
+ if (caller_pid > 0) {
+ if (__check_caller_by_pid(caller_pid) < 0) {
+ _E("Invalid caller pid");
+ goto end;
+ }
+ }
+ _debug_init();
+ }
+
switch (pkt->cmd) {
case PAD_CMD_VISIBILITY:
ret = __dispatch_cmd_hint(kb, METHOD_VISIBILITY);
@@ -1558,6 +1660,7 @@ static int __before_loop(int argc, char **argv)
static void __after_loop(void)
{
+ _debug_fini();
_launcher_info_unload(launcher_info_list);
if (label_monitor)
diff --git a/src/launchpad_debug.c b/src/launchpad_debug.c
new file mode 100644
index 0000000..10afec8
--- /dev/null
+++ b/src/launchpad_debug.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <linux/limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <bundle_internal.h>
+
+#include "launchpad_common.h"
+#include "launchpad_debug.h"
+#include "debugger_info.h"
+#include "key.h"
+
+#define DEBUGGER_INFO_PATH "/usr/share/aul"
+
+static int debug_initialized;
+static GList *debugger_info_list;
+static debugger_info_h debugger_info;
+static GList *extra_argv_list;
+
+int _debug_create_argv(int *argc, char ***argv, bool *attach)
+{
+ int new_argc;
+ char **new_argv;
+ const char *exe;
+ const char *extra_argv;
+ const char *attach_str;
+ GList *iter;
+ int i;
+
+ if (argc == NULL || argv == NULL || attach == NULL) {
+ _E("[DEBUG] Invalid parameter");
+ return -1;
+ }
+
+ if (debugger_info == NULL)
+ return 0;
+
+ exe = _debugger_info_get_exe(debugger_info);
+ if (exe == NULL)
+ return -1;
+
+ attach_str = _debugger_info_get_attach(debugger_info);
+ if (attach_str && strcasecmp(attach_str, "true") == 0)
+ *attach = true;
+
+ new_argc = g_list_length(extra_argv_list) + 1;
+ new_argv = (char **)calloc(new_argc, sizeof(char *));
+ if (new_argv == NULL) {
+ _E("out of memory");
+ return -1;
+ }
+
+ i = LOADER_ARG_PATH;
+ new_argv[i++] = strdup(exe);
+
+ iter = g_list_first(extra_argv_list);
+ while (iter) {
+ extra_argv = (const char *)iter->data;
+ if (extra_argv)
+ new_argv[i++] = strdup(extra_argv);
+
+ iter = g_list_next(iter);
+ }
+
+ *argc = new_argc;
+ *argv = new_argv;
+ _D("[DEBUG] argc: %d, argv[0]: %s",
+ new_argc, new_argv[LOADER_ARG_PATH]);
+
+ return 0;
+}
+
+void _debug_destroy_argv(int argc, char **argv)
+{
+ int i;
+
+ if (argv == NULL)
+ return;
+
+ for (i = 0; i < argc; i++)
+ free(argv[i]);
+ free(argv);
+}
+
+int _debug_get_caller_pid(bundle *kb)
+{
+ const char *pid_str;
+ int pid;
+
+ pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
+ if (pid_str == NULL)
+ pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
+
+ if (pid_str == NULL)
+ return -1;
+
+ pid = atoi(pid_str);
+ if (pid <= 1)
+ return -1;
+
+ return pid;
+}
+
+static int __redirect_std_fds(bundle *kb)
+{
+ char path[PATH_MAX];
+ char err_buf[1024];
+ int fd;
+ int caller_pid;
+
+ if (kb == NULL) {
+ _E("[DEBUG] Invalid parameter");
+ return -1;
+ }
+
+ caller_pid = _debug_get_caller_pid(kb);
+ if (caller_pid < 0) {
+ _E("[DEBUG] Failed to get caller pid");
+ return -1;
+ }
+
+ /* stdout */
+ snprintf(path, sizeof(path), "/proc/%d/fd/1", caller_pid);
+ fd = open(path, O_WRONLY);
+ if (fd < 0) {
+ _E("[DEBUG] Failed to open %s [%s]", path,
+ strerror_r(errno, err_buf, sizeof(err_buf)));
+ return -1;
+ }
+ dup2(fd, 1);
+ close(fd);
+
+ /* stderr */
+ snprintf(path, sizeof(path), "/proc/%d/fd/2", caller_pid);
+ fd = open(path, O_WRONLY);
+ if (fd < 0) {
+ _E("[DEBUG] Failed to open %s [%s]", path,
+ strerror_r(errno, err_buf, sizeof(err_buf)));
+ return -1;
+ }
+ dup2(fd, 2);
+ close(fd);
+
+ return 0;
+}
+
+static void __add_extra_argv(gpointer data, gpointer user_data)
+{
+ const char *key = (const char *)data;
+ bundle *kb = (bundle *)user_data;
+ const char *str;
+ const char **str_arr = NULL;
+ int len = 0;
+ int i;
+
+ if (key == NULL || kb == NULL)
+ return;
+
+ _D("[DEBUG] key: %s", key);
+ if (bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) {
+ str_arr = bundle_get_str_array(kb, key, &len);
+ } else {
+ str = bundle_get_val(kb, key);
+ if (str) {
+ str_arr = &str;
+ len = 1;
+ }
+ }
+
+ for (i = 0; i < len; i++) {
+ if (str_arr[i] == NULL)
+ break;
+
+ extra_argv_list = g_list_append(extra_argv_list,
+ strdup(str_arr[i]));
+ }
+
+ if (str_arr)
+ bundle_del(kb, key);
+}
+
+static void __set_debug_env(gpointer data, gpointer user_data)
+{
+ const char *key = (const char *)data;
+ bundle *kb = (bundle *)user_data;
+ const char *str;
+ const char **str_arr = NULL;
+ int len = 0;
+ int i;
+ char buf[LINE_MAX] = {0,};
+
+ if (key == NULL || kb == NULL)
+ return;
+
+ _D("[DEBUG] key: %s", key);
+ if (bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) {
+ str_arr = bundle_get_str_array(kb, key, &len);
+ } else {
+ str = bundle_get_val(kb, key);
+ if (str) {
+ str_arr = &str;
+ len = 1;
+ }
+ }
+
+ if (str_arr == NULL)
+ return;
+
+ strncat(buf, str_arr[0], sizeof(buf) - strlen(buf) - 1);
+ for (i = 1; i < len; i++) {
+ if (str_arr[i] == NULL)
+ break;
+
+ strncat(buf, ",", sizeof(buf) - strlen(buf) - 1);
+ strncat(buf, str_arr[1], sizeof(buf) - strlen(buf) - 1);
+ }
+
+ bundle_del(kb, key);
+ _D("[DEBUG] name: %s, value: %s", key, buf);
+ setenv(key, buf, 1);
+}
+
+static void __remove_file(gpointer data, gpointer user_data)
+{
+ const char *file = (const char *)data;
+
+ if (file == NULL)
+ return;
+
+ _D("[DEBUG] file: %s", file);
+ if (access(file, F_OK) == 0) {
+ if (remove(file) != 0)
+ _W("[DEBUG] Failed to remove %s", file);
+ }
+}
+
+void _debug_prepare_debugger(bundle *kb)
+{
+ const char *debugger;
+ GList *list;
+ int ret;
+
+ if (kb == NULL)
+ return;
+
+ debugger = bundle_get_val(kb, AUL_K_SDK);
+ if (debugger == NULL)
+ return;
+
+ _D("[DEBUG] debugger: %s", debugger);
+ debugger_info = _debugger_info_find(debugger_info_list, debugger);
+ if (debugger_info == NULL)
+ return;
+
+ ret = __redirect_std_fds(kb);
+ if (ret < 0)
+ _E("[DEBUG] Failed to redirect standard fds");
+
+ list = _debugger_info_get_unlink_list(debugger_info);
+ g_list_foreach(list, __remove_file, NULL);
+
+ list = _debugger_info_get_extra_env_list(debugger_info);
+ g_list_foreach(list, __set_debug_env, kb);
+
+ list = _debugger_info_get_extra_key_list(debugger_info);
+ g_list_foreach(list, __add_extra_argv, kb);
+}
+
+int _debug_init(void)
+{
+ if (debug_initialized)
+ return 0;
+
+ debugger_info_list = _debugger_info_load(DEBUGGER_INFO_PATH);
+ if (debugger_info_list == NULL)
+ return -1;
+
+ debug_initialized = 1;
+
+ return 0;
+}
+
+void _debug_fini(void)
+{
+ if (!debug_initialized)
+ return;
+
+ _debugger_info_unload(debugger_info_list);
+}