allow massif logfile option in valgrind
[framework/appfw/debug-launchpad.git] / src / launchpad.c
index c69a95b..aaec35c 100755 (executable)
@@ -19,7 +19,6 @@
  *
  */
 
-
 /*
  * simple AUL daemon - launchpad 
  */
@@ -59,6 +58,7 @@
 #include <sqlite3.h>
 #include <sys/smack.h>
 #include "fileutils.h"
+#include <sys/capability.h>
 
 #define _static_ static inline
 #define POLLFD_MAX 1
 #define SDK_DYNAMIC_ANALYSIS "DYNAMIC_ANALYSIS"
 #define SDK_UNIT_TEST "UNIT_TEST"
 #define SDK_VALGRIND "VALGRIND"
+#define SDK_LD_FLAG "LD_FLAG"
 
 /* DLP is short for debug-launchpad */
 #define DLP_K_DEBUG_ARG "__DLP_DEBUG_ARG__"
 #define DLP_K_UNIT_TEST_ARG "__DLP_UNIT_TEST_ARG__"
 #define DLP_K_VALGRIND_ARG "__DLP_VALGRIND_ARG__"
-
-#define PATH_GDBSERVER "/home/developer/sdk_tools/gdbserver/gdbserver"
-#define PATH_VALGRIND "/home/developer/sdk_tools/valgrind/usr/bin/valgrind"
-#define PATH_DA_SO "/usr/lib/da_probe_osp.so"
-#define PATH_NATIVE_APP "/opt/apps/"
-
+#define DLP_K_LD_FLAG "__DLP_LD_FLAG__"
+
+#define PATH_GDBSERVER "/home/developer/sdk_tools/gdbserver/gdbserver"
+#define PATH_VALGRIND  "/home/developer/sdk_tools/valgrind/usr/bin/valgrind"
+#define PATH_DA_SO     "/usr/lib/da_probe_tizen.so"
+#define PATH_NATIVE_APP        "/opt/apps/"
+
+#define OPT_VALGRIND_LOGFILE           "--log-file="
+#define OPT_VALGRIND_LOGFILE_FIXED     "--log-file=/tmp/valgrind_result.txt"
+#define PATH_VALGRIND_LOGFILE          "/tmp/valgrind_result.txt"
+#define OPT_VALGRIND_XMLFILE           "--xml-file="
+#define OPT_VALGRIND_XMLFILE_FIXED     "--xml-file=/tmp/valgrind_result.xml"
+#define PATH_VALGRIND_XMLFILE          "/tmp/valgrind_result.xml"
+#define OPT_VALGRIND_MASSIFFILE                "--massif-out-file="
+#define OPT_VALGRIND_MASSIFFILE_FIXED  "--massif-out-file=/tmp/valgrind_result.xml"
+
+#if (ARCH==arm)
+#define PATH_MEMCHECK  "/opt/home/developer/sdk_tools/valgrind/usr/lib/valgrind/memcheck-arm-linux"
+#elif (ARCH==x86)
+#define PATH_MEMCHECK  "/opt/home/developer/sdk_tools/valgrind/usr/lib/valgrind/memcheck-x86-linux"
+#endif
+
+#define POLL_VALGRIND_LOGFILE          0x00000001
+#define POLL_VALGRIND_XMLFILE          0x00000002
+
+#define CAPABILITY_SET_ORIGINAL                0
+#define CAPABILITY_SET_INHERITABLE     1
+
+static int need_to_set_inh_cap_after_fork = 0;
 static char *launchpad_cmdline;
 static int initialized = 0;
 
+static int poll_outputfile = 0;
+static int is_gdbserver_launched;
 
 void __set_oom();
 void __set_env(app_info_from_db * menu_info, bundle * kb);
@@ -128,29 +154,65 @@ void __set_oom()
        fclose(fp);
 }
 
-void __set_sdk_env(app_info_from_db* menu_info, char* str) {
+void __set_sdk_env(app_info_from_db* menu_info, char* str, bundle * kb) {
        char buf_pkgname[MAX_LOCAL_BUFSZ];
        char buf[MAX_LOCAL_BUFSZ];
        int ret;
 
        _D("key : %s / value : %s", AUL_K_SDK, str);
        /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/
-       /* GCOV_PREFIX contains the prefix to add to the absolute paths in the object file. */
-       /*              Prefix can be absolute, or relative. The default is no prefix.  */
+       /* GCOV_PREFIX contains the prefix to add to the absolute paths */
+       /*      in the object file. Prefix can be absolute, or relative.*/
+       /*      The default is no prefix.  */
        /* GCOV_PREFIX_STRIP indicates the how many initial directory names */
-       /*              to stripoff the hardwired absolute paths. Default value is 0. */
+       /*      to stripoff the hardwired absolute paths. Default value is 0. */
        if (strncmp(str, SDK_CODE_COVERAGE, strlen(str)) == 0) {
                strncpy(buf_pkgname,_get_pkgname(menu_info),MAX_LOCAL_BUFSZ-1);
                buf_pkgname[MAX_LOCAL_BUFSZ-1]='\0';
-               snprintf(buf, MAX_LOCAL_BUFSZ, PATH_TMP"/%s"PATH_DATA, strtok(buf_pkgname,"."));
+               snprintf(buf, MAX_LOCAL_BUFSZ, PATH_TMP"/%s"PATH_DATA
+                       , strtok(buf_pkgname,"."));
                ret = setenv("GCOV_PREFIX", buf, 1);
                _D("GCOV_PREFIX : %d", ret);
                ret = setenv("GCOV_PREFIX_STRIP", "0", 1);
                _D("GCOV_PREFIX_STRIP : %d", ret);
-       } else if (strncmp(str, SDK_DYNAMIC_ANALYSIS, strlen(str)) == 0) {
+       }
+       else if (strncmp(str, SDK_DYNAMIC_ANALYSIS, strlen(str)) == 0)
+       {
                ret = setenv("LD_PRELOAD", PATH_DA_SO, 1);
                _D("LD_PRELOAD : %d", ret);
        }
+       else if (strncmp(str, SDK_LD_FLAG, strlen(str)) == 0)
+       {
+               const char *flag_str = NULL;
+               const char **flag_str_array = NULL;
+               int flag_len;
+               if(bundle_get_type(kb, DLP_K_LD_FLAG) & BUNDLE_TYPE_ARRAY) {
+                       flag_str_array = bundle_get_str_array(kb, DLP_K_LD_FLAG, &flag_len);
+               } else {
+                       flag_str = bundle_get_val(kb, DLP_K_LD_FLAG);
+                       if(flag_str) {
+                               flag_str_array = &flag_str;
+                               flag_len = 1;
+                       }
+               }
+               if(flag_str_array != NULL) {
+                       int i;
+                       char * f_name;
+                       char * f_value;
+                       for (i = 0; i < flag_len; i++) {
+                               strncpy(buf,flag_str_array[i],MAX_LOCAL_BUFSZ);
+                               f_name = strtok(buf,"=");
+                               f_value = strtok(NULL,"=");
+                               if(f_value) {
+                                       ret = setenv(f_name,f_value,1);
+                                       _D("LD_FLAG : %s %s %d",f_name,f_value,ret);
+                               } else {
+                                       _E("LD_FLAG : Wrong option! %s", flag_str_array[i]);
+                               }
+                       }
+               }
+
+       }
 }
 
 
@@ -174,13 +236,13 @@ void __set_env(app_info_from_db * menu_info, bundle * kb)
                if(str_array != NULL) {
                        for (i = 0; i < len; i++) {
                                _D("index : [%d]", i);
-                               __set_sdk_env(menu_info, (char *)str_array[i]);
+                               __set_sdk_env(menu_info, (char *)str_array[i], kb);
                        }
                }
        } else {
                str = bundle_get_val(kb, AUL_K_SDK);
                if(str != NULL) {
-                       __set_sdk_env(menu_info, (char *)str);
+                       __set_sdk_env(menu_info, (char *)str, kb);
                }
        }
        if (menu_info->hwacc != NULL)
@@ -207,9 +269,13 @@ int __prepare_exec(const char *pkg_name,
 
        /* SET PRIVILEGES*/
        if(bundle_get_val(kb, AUL_K_PRIVACY_APPID) == NULL) {
-               _D("pkg_name : %s / pkg_type : %s / app_path : %s ", pkg_name, menu_info->pkg_type, app_path);
-               if ((ret = __set_access(pkg_name, menu_info->pkg_type, app_path)) < 0) {
-                        _D("fail to set privileges - check your package's credential : %d\n", ret);
+               _D("pkg_name : %s / pkg_type : %s / app_path : %s ", pkg_name
+                       , menu_info->pkg_type, app_path);
+               if ((ret = __set_access(pkg_name, menu_info->pkg_type
+                       , app_path)) < 0) 
+               {
+                        _D("fail to set privileges - check your package's credential : %d\n"
+                               , ret);
                        return -1;
                }
        }
@@ -270,7 +336,8 @@ char** __add_arg(bundle * kb, char **argv, int *margc, const char *key)
                if(strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
                        || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0)
                {
-                       new_argv = (char **) realloc(argv, sizeof(char *) * (*margc+len+2));
+                       new_argv = (char **) realloc(argv
+                               , sizeof(char *) * (*margc+len+2));
                        if(!new_argv) {
                                _E("realloc fail (key = %s)", key);
                                exit(-1);
@@ -288,7 +355,8 @@ char** __add_arg(bundle * kb, char **argv, int *margc, const char *key)
                        _D("gid : %d", getgid());
                        _D("egid : %d", getegid());
                } else {
-                       new_argv = (char **) realloc(argv, sizeof(char *) * (*margc+len+1));
+                       new_argv = (char **) realloc(argv
+                               , sizeof(char *) * (*margc+len+1));
                        if(!new_argv) {
                                _E("realloc fail (key = %s)", key);
                                exit(-1);
@@ -303,7 +371,8 @@ char** __add_arg(bundle * kb, char **argv, int *margc, const char *key)
                if(strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
                        || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0)
                {
-                       new_argv = (char **) realloc(argv, sizeof(char *) * (*margc+2));
+                       new_argv = (char **) realloc(argv
+                               , sizeof(char *) * (*margc+2));
                        if(!new_argv) {
                                _E("realloc fail (key = %s)", key);
                                exit(-1);
@@ -312,7 +381,7 @@ char** __add_arg(bundle * kb, char **argv, int *margc, const char *key)
                                new_argv[i] = new_argv[i-1];
                        }
                        // need to add new_argv[0]
-                       *margc++;
+                       (*margc)++;
                }
        }
 
@@ -333,6 +402,9 @@ char **__create_argc_argv(bundle * kb, int *margc, const char *app_path)
 
        argc = bundle_export_to_argv(kb, &argv);
        if (argv) {
+               for(i=1; i<argc; i++) {
+                       argv[i] = strdup(argv[i]);
+               }
                argv[0] = strdup(app_path);
        } else {
                _E("bundle_export_to_argv error");
@@ -348,23 +420,41 @@ char **__create_argc_argv(bundle * kb, int *margc, const char *app_path)
                        len = 1;
                }
        }
-       if(str_array != NULL) {
-               for (i = 0; i < len; i++) {
-                       if(str_array[i] == NULL) break;
-                       _D("index : [%d]", i);
-                       if (strncmp(str_array[i], SDK_DEBUG, strlen(str_array[i])) == 0) {
-                               char buf[MAX_LOCAL_BUFSZ];
-                               if (argv[0]) free(argv[0]);
-                               sprintf(buf,"%s.exe",app_path);
-                               argv[0] = strdup(buf);
-                               new_argv = __add_arg(kb, argv, &argc, DLP_K_DEBUG_ARG);
-                               new_argv[0] = strdup(PATH_GDBSERVER);
-                       } else if (strncmp(str_array[i], SDK_VALGRIND, strlen(str_array[i])) == 0) {
-                               new_argv = __add_arg(kb, argv, &argc, DLP_K_VALGRIND_ARG);
-                               new_argv[0] = strdup(PATH_VALGRIND);
-                       } else if (strncmp(str_array[i], SDK_UNIT_TEST, strlen(str_array[i])) == 0) {
-                               new_argv = __add_arg(kb, argv, &argc, DLP_K_UNIT_TEST_ARG);
-                       }
+       if(str_array == NULL) {
+               *margc = argc;
+               return argv;
+       }
+
+       for (i = 0; i < len; i++) {
+               if(str_array[i] == NULL) break;
+               _D("index : [%d]", i);
+               /* gdbserver */
+               if (strncmp(str_array[i], SDK_DEBUG, strlen(str_array[i])) == 0)
+               {
+                       char buf[MAX_LOCAL_BUFSZ];
+                       if (argv[0]) free(argv[0]);
+                       snprintf(buf,MAX_LOCAL_BUFSZ,"%s.exe",app_path);
+                       argv[0] = strdup(buf);
+                       new_argv = __add_arg(kb, argv, &argc, DLP_K_DEBUG_ARG);
+                       new_argv[0] = strdup(PATH_GDBSERVER);
+                       argv = new_argv;
+               }
+               /* valgrind */
+               else if (strncmp(str_array[i], SDK_VALGRIND
+                       , strlen(str_array[i])) == 0)
+               {
+                       new_argv = __add_arg(kb, argv, &argc
+                               , DLP_K_VALGRIND_ARG);
+                       new_argv[0] = strdup(PATH_VALGRIND);
+                       argv = new_argv;
+               }
+               /* unit test */
+               else if (strncmp(str_array[i], SDK_UNIT_TEST
+                       , strlen(str_array[i])) == 0)
+               {
+                       new_argv = __add_arg(kb, argv, &argc
+                               , DLP_K_UNIT_TEST_ARG);
+                       argv = new_argv;
                }
        }
 
@@ -519,7 +609,9 @@ void __modify_bundle(bundle * kb, int caller_pid,
        bundle_del(kb, AUL_K_HWACC);
 
        /* Parse app_path to retrieve default bundle*/
-       if (cmd == APP_START || cmd == APP_START_RES || cmd == APP_OPEN || cmd == APP_RESUME) {
+       if (cmd == APP_START || cmd == APP_START_RES || cmd == APP_OPEN
+               || cmd == APP_RESUME)
+       {
                char *ptr;
                char exe[MAX_PATH_LEN];
                int flag;
@@ -691,7 +783,7 @@ void __send_result_to_caller(int clifd, int ret)
 }
 
 static app_info_from_db *_get_app_info_from_bundle_by_pkgname(
-                                                       const char *pkgname, bundle *kb)
+       const char *pkgname, bundle *kb)
 {
        app_info_from_db *menu_info;
 
@@ -726,16 +818,19 @@ int get_native_appid(const char* app_path, char** appid) {
                return -1;
        }
 
-       if (strlen(*appid)!=APPID_LEN) {
+       if (strlen(*appid) != APPID_LEN) {
                _E("wrong native appid : %s", *appid);
                return -1;
        }
 
-       if (strlen(app_path)<sizeof(PATH_NATIVE_APP)+APPID_LEN-1) {
+       if (strlen(app_path) < sizeof(PATH_NATIVE_APP)+APPID_LEN-1) {
                _E("wrong native app_path : %s", app_path);
                return -1;
-       } else if (strncmp(app_path,PATH_NATIVE_APP,sizeof(PATH_NATIVE_APP)-1)
-               || strncmp(&app_path[sizeof(PATH_NATIVE_APP)-1],*appid,APPID_LEN)) {
+       }
+       else if ( strncmp(app_path, PATH_NATIVE_APP, sizeof(PATH_NATIVE_APP)-1)
+               || strncmp(&app_path[sizeof(PATH_NATIVE_APP)-1]
+               , *appid,APPID_LEN) )
+       {
                _E("wrong native app_path : %s", app_path);
                return -1;
        }
@@ -744,7 +839,9 @@ int get_native_appid(const char* app_path, char** appid) {
        return 0;
 }
 
-int apply_smack_rules(const char* subject, const char* object, const char* access_type) {
+int apply_smack_rules(const char* subject, const char* object
+       , const char* access_type)
+{
        struct smack_accesses *rules = NULL;
 
        _D("apply_smack_rules : %s %s %s", subject, object, access_type);
@@ -771,6 +868,286 @@ int apply_smack_rules(const char* subject, const char* object, const char* acces
        return 0;
 }
 
+int __prepare_valgrind_outputfile(bundle *kb)
+{
+       const char *str = NULL;
+       const char **str_array = NULL;
+       int len = 0;
+       int i;
+
+       if(bundle_get_type(kb, DLP_K_VALGRIND_ARG) & BUNDLE_TYPE_ARRAY) {
+               str_array = bundle_get_str_array(kb, DLP_K_VALGRIND_ARG, &len);
+       } else {
+               str = bundle_get_val(kb, DLP_K_VALGRIND_ARG);
+               if(str) {
+                       str_array = &str;
+                       len = 1;
+               }
+       }
+       if(str_array == NULL) return 0;
+
+       for (i = 0; i < len; i++) {
+               if(str_array[i] == NULL) break;
+               /* valgrind log file option */
+               if (strncmp(str_array[i], OPT_VALGRIND_LOGFILE
+                       , sizeof(OPT_VALGRIND_LOGFILE)-1) == 0)
+               {
+                       if(strcmp(str_array[i], OPT_VALGRIND_LOGFILE_FIXED))
+                       {
+                               _E("wrong valgrind option(%s). It should be %s"
+                                       , str_array[i]
+                                       , OPT_VALGRIND_LOGFILE_FIXED);
+                               return -1;
+                       }else{
+                               poll_outputfile |= POLL_VALGRIND_LOGFILE;
+                               if(remove(PATH_VALGRIND_LOGFILE)){
+                                       _D("cannot remove %s"
+                                               , PATH_VALGRIND_LOGFILE);
+                               }
+                       }
+               }
+               /* valgrind xml file option */
+               else if (strncmp(str_array[i], OPT_VALGRIND_XMLFILE
+                       , sizeof(OPT_VALGRIND_XMLFILE)-1) == 0)
+               {
+                       if(strcmp(str_array[i], OPT_VALGRIND_XMLFILE_FIXED))
+                       {
+                               _E("wrong valgrind option(%s). It should be %s"
+                                       , str_array[i]
+                                       , OPT_VALGRIND_XMLFILE_FIXED);
+                               return -1;
+                       }else{
+                               poll_outputfile |= POLL_VALGRIND_XMLFILE;
+                               if(remove(PATH_VALGRIND_XMLFILE)){
+                                       _D("cannot remove %s"
+                                               , PATH_VALGRIND_XMLFILE);
+                               }
+                       }
+               }
+               /* valgrind massif file option */
+               else if (strncmp(str_array[i], OPT_VALGRIND_MASSIFFILE
+                       , sizeof(OPT_VALGRIND_MASSIFFILE)-1) == 0)
+               {
+                       if(strcmp(str_array[i], OPT_VALGRIND_MASSIFFILE_FIXED))
+                       {
+                               _E("wrong valgrind option(%s). It should be %s"
+                                       , str_array[i]
+                                       , OPT_VALGRIND_MASSIFFILE_FIXED);
+                               return -1;
+                       }else{
+                               poll_outputfile |= POLL_VALGRIND_XMLFILE;
+                               if(remove(PATH_VALGRIND_XMLFILE)){
+                                       _D("cannot remove %s"
+                                               , PATH_VALGRIND_XMLFILE);
+                               }
+                       }
+               }
+       }
+       return 0;
+}
+
+extern int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
+
+int __adjust_process_capability(int sv)
+{
+       static struct __user_cap_header_struct h;
+       static struct __user_cap_data_struct ori_d[_LINUX_CAPABILITY_U32S_2];
+       static struct __user_cap_data_struct inh_d[_LINUX_CAPABILITY_U32S_2];
+       static int isinit = 0;
+
+       if(isinit==0) {
+               h.version = _LINUX_CAPABILITY_VERSION_2;
+               h.pid = getpid();
+
+               capget(&h, ori_d);
+               capget(&h, inh_d);
+
+               inh_d[CAP_TO_INDEX(CAP_NET_RAW)].inheritable |=
+                       CAP_TO_MASK(CAP_NET_RAW);
+               inh_d[CAP_TO_INDEX(CAP_SYS_CHROOT)].inheritable |=
+                       CAP_TO_MASK(CAP_SYS_CHROOT);
+
+               isinit++;
+
+               if(sv == CAPABILITY_SET_ORIGINAL) return 0;
+       }
+
+       if(isinit==0) {
+               _E("__adjust_process_capability init failed");
+               return -1;
+       }
+
+       if(sv == CAPABILITY_SET_ORIGINAL) {
+               h.pid = getpid();
+               if (capset(&h, ori_d) < 0) {
+                       _E("Capability setting error");
+                       return -1;
+               }
+       }
+       else if (sv == CAPABILITY_SET_INHERITABLE) {
+               h.pid = getpid();
+               if (capset(&h, inh_d) < 0) {
+                       _E("Capability setting error");
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+int __adjust_file_capability(const char * path)
+{
+       if(cap_set_file(path,cap_from_text("CAP_NET_RAW,CAP_SYS_CHROOT+i"))) {
+               _E("cap_set_file failed : %s", path);
+               return -1;
+       }
+       return 0;
+}
+
+int __prepare_fork(bundle *kb, char *appid)
+{
+       const char *str = NULL;
+       const char **str_array = NULL;
+       int len = 0;
+       int i;
+
+       need_to_set_inh_cap_after_fork=0;
+       poll_outputfile = 0;
+       if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
+               str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
+       } else {
+               str = bundle_get_val(kb, AUL_K_SDK);
+               if(str) {
+                       str_array = &str;
+                       len = 1;
+               }
+       }
+       if(str_array == NULL) return 0;
+
+       is_gdbserver_launched = 0;
+       gdbserver_pid = -1;
+       gdbserver_app_pid = -1;
+
+       for (i = 0; i < len; i++) {
+               if(str_array[i] == NULL) break;
+               /* gdbserver */
+               if (strncmp(str_array[i], SDK_DEBUG, strlen(str_array[i])) == 0)
+               {
+                       if(apply_smack_rules("sdbd",appid,"w")) {
+                               _E("unable to set sdbd rules");
+                               return -1;
+                       }
+
+                       // FIXME: set gdbfolder to 755 also
+                       if(dlp_chmod(PATH_GDBSERVER
+                               , S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP
+                               |S_IROTH|S_IXOTH
+                               , 1))
+                       {
+                               _D("unable to set 755 to %s", PATH_GDBSERVER);
+                       }
+                       __adjust_file_capability(PATH_GDBSERVER);
+                       need_to_set_inh_cap_after_fork++;
+                       is_gdbserver_launched++;
+               }
+               /* valgrind */
+               else if (strncmp(str_array[i], SDK_VALGRIND
+                       , strlen(str_array[i])) == 0)
+               {
+                       if (__prepare_valgrind_outputfile(kb) == -1) 
+                               return -1;
+                       __adjust_file_capability(PATH_MEMCHECK);
+               }
+       }
+       return 0;
+}
+
+/* chmod and chsmack to read file without root privilege */
+void __chmod_chsmack_toread(const char * path)
+{
+       /* chmod */
+       if(dlp_chmod(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 0))
+       {
+               _E("unable to set 644 to %s", path);
+       }else{
+               _D("set 644 to %s", path);
+       }
+
+       /* chsmack */
+       if(smack_setlabel(path, "*", SMACK_LABEL_ACCESS))
+       {
+               _E("failed chsmack -a \"*\" %s", path);
+       }else{
+               _D("chsmack -a \"*\" %s", path);
+       }
+
+       return;
+}
+
+/* waiting for creating outputfile by child process */
+void __waiting_outputfile()
+{
+       int wait_count = 0;
+       while(poll_outputfile && wait_count<10) {
+               /* valgrind log file */
+               if( (poll_outputfile & POLL_VALGRIND_LOGFILE) 
+                       && (access(PATH_VALGRIND_LOGFILE,F_OK)==0) )
+               {
+                       __chmod_chsmack_toread(PATH_VALGRIND_LOGFILE);
+                       poll_outputfile &= ~POLL_VALGRIND_LOGFILE;
+               }
+
+               /* valgrind xml file */
+               if( (poll_outputfile & POLL_VALGRIND_XMLFILE)
+                       && (access(PATH_VALGRIND_XMLFILE,F_OK)==0) )
+               {
+                       __chmod_chsmack_toread(PATH_VALGRIND_XMLFILE);
+                       poll_outputfile &= ~POLL_VALGRIND_XMLFILE;
+               }
+               
+               if(poll_outputfile) {
+                       _D("-- now wait for creating the file --");
+                       usleep(50 * 1000);      /* 50ms sleep*/
+                       wait_count++;
+               }
+       }
+
+       if(wait_count==10) _E("faild to waiting");
+       return;
+}
+
+int __stdout_stderr_redirection(int defpid)
+{
+       char defpath[UNIX_PATH_MAX];
+       int deffd, result=0; 
+
+       /* stdout */
+       snprintf(defpath, UNIX_PATH_MAX, "/proc/%d/fd/1", defpid);
+       deffd = open(defpath,O_WRONLY);
+       if(deffd < 0) {
+               _E("opening caller(%d) stdout failed due to %s"
+                       , defpid, strerror(errno));
+               result++;
+       }else{
+               dup2(deffd, 1);
+               close(deffd);
+       }
+
+       /* stderr */
+       snprintf(defpath, UNIX_PATH_MAX, "/proc/%d/fd/2", defpid);
+       deffd = open(defpath,O_WRONLY);
+       if(deffd < 0) {
+               _E("opening caller(%d) stderr failed due to %s"
+                       , defpid,strerror(errno));
+               result+=2;
+       }else{
+               dup2(deffd, 2);
+               close(deffd);
+       }
+
+       return result;
+}
+
 void __launchpad_main_loop(int main_fd)
 {
        bundle *kb = NULL;
@@ -785,6 +1162,7 @@ void __launchpad_main_loop(int main_fd)
        int is_real_launch = 0;
 
        char sock_path[UNIX_PATH_MAX] = {0,};
+       char * appid = NULL;
 
        pkt = __app_recv_raw(main_fd, &clifd, &cr);
        if (!pkt) {
@@ -820,86 +1198,82 @@ void __launchpad_main_loop(int main_fd)
                goto end;
        }
 
+       {
+               int rc = get_native_appid(app_path,&appid);
+               if(rc!=0 || appid==NULL) {
+                       _E("unable to get native appid");
+                       if(appid){
+                               free(appid);
+                               appid = NULL;
+                       }
+                       goto end;
+               }
+       }
+
        __modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
        pkg_name = _get_pkgname(menu_info);
 
        PERF("get package information & modify bundle done");
 
-       {
-               const char *str = NULL;
-               const char **str_array = NULL;
-               int len = 0;
+       if(__prepare_fork(kb,appid) == -1) goto end;
 
-               if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
-                       str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
-               } else {
-                       str = bundle_get_val(kb, AUL_K_SDK);
-                       if(str) {
-                               str_array = &str;
-                               len = 1;
-                       }
+       pid = fork();
+       if (pid == 0) {
+               if(need_to_set_inh_cap_after_fork) {
+                       __adjust_process_capability(CAPABILITY_SET_INHERITABLE);
                }
-               if(str_array != NULL) {
-                       int i;
-                       for (i = 0; i < len; i++) {
-                               if(str_array[i] == NULL) break;
-                               if (strncmp(str_array[i], SDK_DEBUG, strlen(str_array[i])) == 0) {
-                                       char * appid = NULL;
-                                       int rc = get_native_appid(app_path,&appid);
-                                       if(rc!=0 || appid==NULL) {
-                                               _E("unable to get native appid");
-                                               if(appid) free(appid);
-                                               goto end;
-                                       }else if(apply_smack_rules("sdbd",appid,"w")) {
-                                               _E("unable to set sdbd rules");
-                                               if(appid) free(appid);
-                                               goto end;
-                                       }
-                                       if(appid) free(appid);
-
-                                       // FIXME: set gdbfolder to 755 also
-                                       if(dlp_chmod(PATH_GDBSERVER, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH, 1) < 0)
-                                       {
-                                               _D("unable to set 755 to %s", PATH_GDBSERVER);
-                                       }
-                               }
-                       }
+               PERF("fork done");
+               _D("lock up test log(no error) : fork done");
+
+               close(clifd);
+               close(main_fd);
+               __signal_unset_sigchld();
+               __signal_fini();
+
+               snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX
+                       , getpid());
+               unlink(sock_path);
+
+               if(__stdout_stderr_redirection(__get_caller_pid(kb))) {
+                       _E("__stdout_stderr_redirection fail");
                }
 
-               pid = fork();
-               if (pid == 0) {
-                       PERF("fork done");
-                       _D("lock up test log(no error) : fork done");
+               PERF("prepare exec - first done");
+               _D("lock up test log(no error) : prepare exec - first done");
 
-                       close(clifd);
-                       close(main_fd);
-                       __signal_unset_sigchld();
-                       __signal_fini();
+               if (__prepare_exec(pkg_name, app_path,
+                                  menu_info, kb) < 0) {
+                       _E("preparing work fail to launch - "
+                          "can not launch %s\n", pkg_name);
+                       exit(-1);
+               }
 
-                       snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, getpid());
-                       unlink(sock_path);
+               PERF("prepare exec - second done");
+               _D("lock up test log(no error) : prepare exec - second done");
 
-                       PERF("prepare exec - first done");
-                       _D("lock up test log(no error) : prepare exec - first done");
+               __real_launch(app_path, kb);
 
-                       if (__prepare_exec(pkg_name, app_path,
-                                          menu_info, kb) < 0) {
-                               _E("preparing work fail to launch - "
-                                  "can not launch %s\n", pkg_name);
-                               exit(-1);
-                       }
+               exit(-1);
+       }
 
-                       PERF("prepare exec - second done");
-                       _D("lock up test log(no error) : prepare exec - second done");
+       if(is_gdbserver_launched) {
+               char buf[MAX_LOCAL_BUFSZ];
 
-                       __real_launch(app_path, kb);
+               usleep(100 * 1000);     /* 100ms sleep */
+               snprintf(buf, MAX_LOCAL_BUFSZ, "%s.exe", app_path);
+               gdbserver_app_pid = __proc_iter_cmdline(NULL, buf);
 
-                       exit(-1);
+               if(gdbserver_app_pid == -1) {
+                       _E("faild to get app pid");
+               } else {
+                       gdbserver_pid = pid;
+                       pid = gdbserver_app_pid;
                }
-               _D("==> real launch pid : %d %s\n", pid, app_path);
-               is_real_launch = 1;
        }
 
+       _D("==> real launch pid : %d %s\n", pid, app_path);
+       is_real_launch = 1;
+
  end:
        __send_result_to_caller(clifd, pid);
 
@@ -919,6 +1293,8 @@ void __launchpad_main_loop(int main_fd)
                bundle_free(kb);
        if (pkt != NULL)
                free(pkt);
+       if (appid != NULL) 
+               free(appid);
 
        /* Active Flusing for Daemon */
        if (initialized > AUL_POLL_CNT) {
@@ -927,6 +1303,7 @@ void __launchpad_main_loop(int main_fd)
                initialized = 1;
        }
 
+       if(poll_outputfile) __waiting_outputfile();
 }
 
 int __launchpad_pre_init(int argc, char **argv)
@@ -983,6 +1360,8 @@ int main(int argc, char **argv)
        struct pollfd pfds[POLLFD_MAX];
        int i;
 
+       __adjust_process_capability(CAPABILITY_SET_ORIGINAL);
+
        /* init without concerning X & EFL*/
        main_fd = __launchpad_pre_init(argc, argv);
        if (main_fd < 0) {