-I/usr/include/vconf
DAEMON_SRCS := \
- da_daemon.c \
- utils.c \
+ main.c \
+ daemon.c \
+ threads.c \
+ da_debug.c \
+ utils.c \
sys_stat.c
LDLIBS_PATH := -L/usr/lib -L./lib/
-lSLP-db-util
LIBS_COMMON := -lglib-2.0 \
-lvconf \
- -laul \
-lcapi-system-info
DEBUG_ON := -DDEBUG=1
+++ /dev/null
-/*
-* DA manager
-*
-* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
-*
-* Contact:
-*
-* Jaewon Lim <jaewon81.lim@samsung.com>
-* Woojin Jung <woojin2.jung@samsung.com>
-* Juyoung Kim <j0.kim@samsung.com>
-*
- * 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.
-*
-* Contributors:
-* - S-Core Co., Ltd
-*
-*/
-
-#include <stdio.h>
-#include <stdlib.h> // for realpath
-#include <string.h> // for strtok, strcpy, strncpy
-#include <assert.h> // for assert
-#include <limits.h> // for realpath
-
-#define __USE_GNU
-#include <sys/types.h> // for socket, mkdir, opendir, readdir
-#include <sys/socket.h> // for socket
-#include <sys/un.h> // for sockaddr_un
-#include <arpa/inet.h> // for sockaddr_in, socklen_t
-#include <sys/stat.h> // for chmod, mkdir
-#include <sys/time.h> // for setitimer
-#include <signal.h> // for sigemptyset, sigset_t, sigaddset, ...
-#include <unistd.h> // for unlink
-#include <pthread.h> // for pthread_mutex_t
-#include <sys/epoll.h> // for epoll apis
-#include <sys/ipc.h> // for shmctl
-#include <sys/shm.h> // for shared memory operation
-#include <dirent.h> // for opendir, readdir
-
-#include "utils.h"
-#include "sys_stat.h"
-#include "da_debug.h"
-
-#define MAX_PATH_LENGTH 256
-#define TARGET_CLIENT_COUNT_MAX 8
-#define READ_BUF_MAX 4096+8
-#define DA_LOG_MAX 4096
-#define APP_INSTALL_PATH_MAX 1024
-#define UDS_NAME "/tmp/da.socket"
-#define DA_INSTALL_DIR "/home/developer/sdk_tools/da/"
-#define DA_INSTALL_PATH "/home/developer/sdk_tools/da/da_install_path"
-#define DA_BUILD_OPTION "/home/developer/sdk_tools/da/da_build_option"
-#define DA_BASE_ADDRESS "/home/developer/sdk_tools/da/da_base_address"
-#define DA_READELF_PATH "/home/developer/sdk_tools/da/readelf"
-#define SCREENSHOT_DIR "/tmp/da"
-#define HOST_MSG_LENGTH 3
-#define SHAREDMEMKEY ((key_t)463825)
-
-#define TIMER_INTERVAL_SEC 1
-#define TIMER_INTERVAL_USEC 0
-
-#define SECOND_INTERVAL
-#define MONITORING_INTERVAL 1 // 1 second
-
-#ifdef SECOND_INTERVAL
-#define __sleep sleep
-#else
-#define __sleep usleep
-#endif
-
-#define RUN_APP_LOADER 1
-
-enum TargetMessageType
-{
- MSG_DEVICE = 1,
- MSG_TIME = 2,
- MSG_SAMPLE = 3,
- MSG_RESOURCE = 4,
- MSG_LOG = 5,
- MSG_IMAGE = 6,
- MSG_TERMINATE = 7,
- MSG_PID = 8,
- MSG_MSG = 9,
- MSG_APPNAME = 10,
- MSG_ERROR = 11
-};
-
-enum HostMessageType
-{
- MSG_HOST_BEGIN = 100,
- MSG_START = 100,
- MSG_STOP = 101,
- MSG_PAUSE = 102,
- MSG_OPTION = 103,
- MSG_ISALIVE = 104,
- MSG_ALIVE = 105,
- MSG_BATT_START = 106,
- MSG_BATT_STOP = 107,
- MSG_HOST_END = 107
-};
-
-enum DAState
-{
- DAS_NONE = 0,
- DAS_START_BEGIN = 1,
- DAS_TARGET_ARM_START = 1,
- DAS_TARGET_X86_START = 2,
- DAS_EMUL_ARM_START = 3,
- DAS_EMUL_X86_START = 4,
- DAS_TARGET_ARM_BATT_START = 5,
- DAS_TARGET_X86_BATT_START = 6,
- DAS_EMUL_ARM_BATT_START = 7,
- DAS_EMUL_X86_BATT_START = 8,
- DAS_START_END = 8,
- DAS_STOP = 9,
- DAS_TERMINATE = 10
-};
-
-typedef struct
-{
- int type;
- int length;
- char data[DA_LOG_MAX];
-} log_t;
-
-//TODO :
-typedef struct
-{
- enum DAState status;
- int serverSockFD;
- int clientSockFD;
-} __daHostInfo;
-
-typedef struct
-{
- enum DAState status;
- int serverSockFD;
- int connectCount;
- int pidCount;
- int clientSockFD[TARGET_CLIENT_COUNT_MAX];
- int execPID[TARGET_CLIENT_COUNT_MAX]; // exec PID by target
-} __daTargetInfo;
-
-typedef struct
-{
- long long allocsize;
- long launch_flag;
-} __daSharedInfo;
-
-typedef struct
-{
- int memid;
- __daSharedInfo* pvalue;
-} __daSharedMem;
-
-typedef struct
-{
- pthread_t timer_thread;
- pthread_mutex_t sendMutex;
- char appPath[128]; // application executable path
- __daSharedMem sharedmem;
- __daHostInfo iHost;
- __daTargetInfo iTarget;
-}__daManager;
-
-__daManager manager =
-{
- -1, // timer_thread handle
- PTHREAD_MUTEX_INITIALIZER, // pthread_mutex_t sendMutex
- { 0, }, // char appPath[128]
- { -1, (void*)-1 }, // __daSharedMem sharedmem
- { DAS_NONE, -1, -1 }, // __daHostInfo iHost
- { DAS_NONE, -1, 0, 0, {0, }, {0, }} // __daTargetInfo iTarget
-};
-
-int aul_terminate_pid(int pid);
-static void* terminate_thread(void* data);
-static void terminate_error(char* errstr, int sendtohost);
-
-#ifdef LOCALTEST
-int aul_terminate_pid(int pid)
-{
- return kill(pid, SIGTERM);
-}
-#endif
-
-int _terminate_pid(int pid)
-{
- int ret;
- pid_t* pids;
- pthread_t term_thread;
-
- ret = aul_terminate_pid(pid);
-
- pids = (pid_t*)malloc(2 * sizeof(pid_t));
- pids[0] = pid;
- pids[1] = -2;
-
- pthread_create(&term_thread, NULL, terminate_thread, pids);
-
- return ret;
-}
-
-// return 0 if succeed
-// return -1 if error occured
-static int remove_indir(const char *dirname)
-{
- DIR *dir;
- struct dirent *entry;
- char path[MAX_PATH_LENGTH];
-
- dir = opendir(dirname);
- if(dir == NULL)
- {
- return -1;
- }
-
- while((entry = readdir(dir)) != NULL)
- {
- if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
- {
- snprintf(path, (size_t) MAX_PATH_LENGTH, "%s/%s", dirname, entry->d_name);
- if (entry->d_type != DT_DIR) // file
- {
- unlink(path);
- }
- else { } // directory
- }
- }
- closedir(dir);
-
- return 0;
-}
-
-// index is started from 0
-int set_launch_flag(int index, int bOn)
-{
- int ret = 0;
- // set launch flag before execute application
- if(__builtin_expect(manager.sharedmem.pvalue != (void*)-1, 1))
- {
- if(bOn != 0)
- manager.sharedmem.pvalue->launch_flag |= (1 << index);
- else
- manager.sharedmem.pvalue->launch_flag &= ~(1 << index);
- }
- else
- ret = -1;
-
- return ret;
-}
-
-long long get_total_alloc_size()
-{
- if(__builtin_expect(manager.sharedmem.pvalue != (void*)-1, 1))
- {
- return manager.sharedmem.pvalue->allocsize;
- }
- else
- {
- return 0L;
- }
-}
-
-// return 0 for normal case
-static int __makeTargetServerSockFD()
-{
- struct sockaddr_un serverAddrUn;
-
- if(manager.iTarget.serverSockFD != -1)
- return -1; // should be never happend
-
- // remove pre unix domain socket file
- // remove(UDS_NAME);
- unlink(UDS_NAME);
-
- if ((manager.iTarget.serverSockFD = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
- {
- LOGE("Target server socket creation failed\n");
- return -1;
- }
- bzero(&serverAddrUn, sizeof(serverAddrUn));
- serverAddrUn.sun_family = AF_UNIX;
- sprintf(serverAddrUn.sun_path, "%s", UDS_NAME);
-
- if (-1 == bind(manager.iTarget.serverSockFD, (struct sockaddr*) &serverAddrUn,
- sizeof(serverAddrUn)))
- {
- LOGE("Target server socket binding failed\n");
- close(manager.iTarget.serverSockFD);
- return -1;
- }
-
- chmod(serverAddrUn.sun_path, 0777);
-
- if (-1 == listen(manager.iTarget.serverSockFD, 5))
- {
- LOGE("Target server socket listening failed\n");
- close(manager.iTarget.serverSockFD);
- return -1;
- }
-
- LOGI("Created TargetSock %d\n", manager.iTarget.serverSockFD);
- return 0;
-}
-
-// return 0 for normal case
-static int __makeHostServerSockFD()
-{
- struct sockaddr_in serverAddrIn;
- int opt = 1;
-
- if(manager.iHost.serverSockFD != -1)
- return -1; // should be never happened
-
- if ((manager.iHost.serverSockFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
- {
- LOGE("Host server socket creation failed\n");
- return -1;
- }
-
- setsockopt(manager.iHost.serverSockFD, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
- memset(&serverAddrIn, 0, sizeof(serverAddrIn));
- serverAddrIn.sin_family = AF_INET;
- serverAddrIn.sin_addr.s_addr = htonl(INADDR_ANY);
- serverAddrIn.sin_port = htons(8001);
-
- // bind address to server socket
- if (-1 == bind(manager.iHost.serverSockFD, (struct sockaddr*) &serverAddrIn, sizeof(serverAddrIn)))
- {
- LOGE("Host server socket binding failed\n");
- close(manager.iHost.serverSockFD);
- return -1;
- }
-
- // enter listen state from client
- if (-1 == listen(manager.iHost.serverSockFD, 5))
- {
- LOGE("Host server socket listening failed\n");
- close(manager.iHost.serverSockFD);
- return -1;
- }
-
- LOGI("Created HostSock %d\n", manager.iHost.serverSockFD);
- return 0;
-}
-
-static int __destroySharedMemory()
-{
- int ret = 0;
- if(manager.sharedmem.pvalue != (void*)-1)
- {
- ret = shmdt(manager.sharedmem.pvalue);
- if(ret == 0)
- manager.sharedmem.pvalue = (void*)-1;
- }
-
- if(manager.sharedmem.memid != -1)
- {
- ret = shmctl(manager.sharedmem.memid, IPC_RMID, 0);
- if(ret == 0)
- manager.sharedmem.memid = -1;
- }
-
- return ret;
-}
-
-// return 0 for normal case
-// return -1 for error case
-static int __createSharedMemory()
-{
- manager.sharedmem.memid = shmget(SHAREDMEMKEY, sizeof(__daSharedInfo), IPC_CREAT | 0666);
- if(manager.sharedmem.memid == -1)
- {
- return -1;
- }
- else
- {
- manager.sharedmem.pvalue = (__daSharedInfo*)shmat(manager.sharedmem.memid, NULL, 0);
- if(manager.sharedmem.pvalue == (void*)-1)
- {
- __destroySharedMemory();
- return -1;
- }
- else
- {
- manager.sharedmem.pvalue->allocsize = 0;
- manager.sharedmem.pvalue->launch_flag = 0;
- return 0;
- }
- }
-}
-
-/*
-static log_t * parsLogData(log_t * log, char* logStr)
-{
-#if 1
- int i, nPos;
-
- if (logStr == NULL || log == NULL)
- return NULL;
-
- //msgType
- for (i = 0, nPos = 0; i < READ_BUF_MAX; i++)
- {
- if (logStr[i] == '|')
- {
- logStr[i] = '\0';
- log->type = atoi(&logStr[nPos]);
- i++;
- break;
- }
- if (logStr[i] == '\0')
- return NULL;
- }
- //length
- for (nPos = i; i < READ_BUF_MAX; i++)
- {
- if (logStr[i] == '|' || logStr[i] == '\0')
- {
- logStr[i] = '\0';
- log->length = atoi(&logStr[nPos]);
- i++;
- break;
- }
- }
- //data
- if ((log->length > 0) && (log->length < DA_LOG_MAX))
- {
- strncpy(log->data, &logStr[i], log->length);
- log->data[log->length] = '\0';
- }
-
- return log;
-
-#else
-
- int i;
- char * startPos = logStr;
- char tempBuf[READ_BUF_MAX];
-
- if(logStr && log)
- {
- log->type = -1;
- log->length = 0;
- log->data[0]='\0';
- //type,length
- for(i=0; i<READ_BUF_MAX; i++)
- {
- if(logStr[i]=='|')
- {
- logStr[i]='\0';
- if(log->type == -1)
- {
- log->type = atoi(startPos);
- startPos = &logStr[i+1];
- }
- else {
- log->length = atoi(startPos);
- startPos = &logStr[i+1];
- break;
- }
- }
- }
- //data
- if((log->length > 0) && (log->length < DA_LOG_MAX) && (startPos))
- {
- strncpy(log->data, startPos, log->length);
- log->data[log->length] = '\0';
- }
- LOGI("log type : %d, length : %d, data : %s\n", log->type, log->length, log->data);
- return log;
- }
- else
- return NULL;
-#endif
-}
-*/
-
-static int get_app_type(void)
-{
- int fd;
- char buf[DA_LOG_MAX];
-
- sprintf(buf, "%s.exe", manager.appPath);
- fd = open(buf, O_RDONLY);
- if(fd != -1)
- {
- close(fd);
- return APP_TYPE_OSP;
- }
- else
- {
- return APP_TYPE_TIZEN;
- }
-}
-
-static int get_executable(char* buf, int buflen)
-{
- int fd;
-
- sprintf(buf, "%s.exe", manager.appPath);
- fd = open(buf, O_RDONLY);
- if(fd != -1)
- {
- close(fd);
- }
- else
- {
- strcpy(buf, manager.appPath);
- }
- return 0;
-}
-
-static int get_app_install_path(char *strAppInstall, int length)
-{
- FILE *fp;
- char buf[DA_LOG_MAX];
- char *p;
- int i;
-
- if ((fp = fopen(DA_INSTALL_PATH, "r")) == NULL)
- {
- LOGE("Failed to open %s\n", DA_INSTALL_PATH);
- return -1;
- }
-
- /*ex : <15> DW_AT_comp_dir : (indirect string, offset: 0x25f): /home/yt/workspace/templatetest/Debug-Tizen-Emulator */
- while (fgets(buf, DA_LOG_MAX, fp) != NULL)
- {
- //name
- p = buf;
- for (i = 0; i < DA_LOG_MAX; i++)
- {
- if (*p == ':')
- break;
- p++;
- }
-
- if (*p != ':')
- break;
- else
- p++;
-
- //(...,offset:...)
- for (; i < DA_LOG_MAX; i++)
- {
- if (*p == '(')
- {
- while (*p != ')')
- {
- p++;
- }
- }
- if (*p == ':')
- break;
- p++;
- }
-
- //find
- if (*p != ':')
- break;
- for (; i < DA_LOG_MAX; i++)
- {
- if (*p == ':' || *p == ' ' || *p == '\t')
- p++;
- else
- break;
- }
-
- //name
- if (strlen(p) <= length)
- {
- sprintf(strAppInstall, "%s", p);
- for (i = 0; i < strlen(p); i++)
- {
- if (strAppInstall[i] == '\n' || strAppInstall[i] == '\t')
- {
- strAppInstall[i] = '\0';
- break;
- }
- }
- fclose(fp);
- return 1;
- }
- }
- fclose(fp);
- return -1;
-}
-
-static int is_app_built_pie(void)
-{
- int result;
- FILE *fp;
- char buf[DA_LOG_MAX];
-
- if((fp = fopen(DA_BUILD_OPTION, "r")) == NULL)
- {
- LOGE("Failed to open %s\n", DA_BUILD_OPTION);
- return -1;
- }
-
- if(fgets(buf, DA_LOG_MAX, fp) != NULL)
- {
- if(strcmp(buf, "DYN\n") == 0)
- result = 1;
- else if(strcmp(buf, "EXEC\n") == 0)
- result = 0;
- else
- result = -1;
- }
- else
- {
- result = -1;
- }
- fclose(fp);
-
- return result;
-}
-
-static int get_app_base_address(int *baseAddress)
-{
- int res;
- FILE *fp;
- char buf[DA_LOG_MAX];
-
- if((fp = fopen(DA_BASE_ADDRESS, "r")) == NULL)
- {
- LOGE("Failed to open %s\n", DA_BASE_ADDRESS);
- return -1;
- }
-
- if(fgets(buf, DA_LOG_MAX, fp) != NULL)
- {
- res = sscanf(buf, "%x", baseAddress);
- }
- else
- {
- res = -1;
- }
- fclose(fp);
-
- return res;
-}
-
-static int is_same_app_process(int pid)
-{
- int ret = 0;
- FILE *fp;
- char buf[DA_LOG_MAX];
- char cmdPath[PATH_MAX];
- char execPath[PATH_MAX];
-
- get_executable(execPath, PATH_MAX);
- sprintf(cmdPath, "/proc/%d/cmdline", pid);
-
- if((fp = fopen(cmdPath, "r")) == NULL)
- {
- return 0;
- }
-
- if(fgets(buf, DA_LOG_MAX, fp) != NULL)
- {
-#if RUN_APP_LOADER
- if(strcmp(buf, manager.appPath) == 0)
-#else
- // use execPath instead of manager.appPath
- if(strcmp(buf, execPath) == 0)
-#endif
- ret = 1;
- else
- ret = 0;
- }
- fclose(fp);
-
- return ret;
-}
-
-static int sendMsgStrToHost(char* str, int msgType, int targetNo)
-{
- static int initialized = 0;
- int pid;
- int is_pie_build;
- int base_address;
- int app_type;
- char log[DA_LOG_MAX];
- char bufDeviceInfo[DA_LOG_MAX];
- char bufAppInstall[APP_INSTALL_PATH_MAX];
-
- switch (msgType)
- {
- case MSG_LOG:
- case MSG_RESOURCE:
- case MSG_SAMPLE:
- case MSG_ERROR:
- if(__builtin_expect(initialized == 0, 0))
- return -1;
- sprintf(log, "%d|%s\n", msgType, str);
- break;
- case MSG_PID:
- LOGI("MSG_PID handling : %s\n", str);
- pid = atoi(str);
- if ((manager.iTarget.execPID[targetNo] != -1) && (pid != manager.iTarget.execPID[targetNo]))
- {
- LOGE("Failed to check pid, pid of msg(%d), stored pid(%d)\n", pid, manager.iTarget.execPID[targetNo]);
- return -1;
- }
- LOGI("pid[%d]=%d\n",targetNo,pid);
- manager.iTarget.execPID[targetNo] = pid;
- manager.iTarget.pidCount++;
-
- {
- char execPath[PATH_MAX];
- char realPath[PATH_MAX];
- char mapsPath[PATH_MAX];
- char appInstallCommand[PATH_MAX];
-
- get_executable(execPath, PATH_MAX);
- if(realpath(execPath, realPath) == NULL)
- {
- LOGW("Failed to get realpath of app\n");
- strcpy(realPath, execPath);
- }
-
- sprintf(mapsPath, "/proc/%d/maps", manager.iTarget.execPID[targetNo]);
- sprintf(appInstallCommand,
- "cat %s | grep %s | cut -d\"-\" -f1 > %s", mapsPath,
- realPath, DA_BASE_ADDRESS);
- LOGI("appInstallCommand is %s\n", appInstallCommand);
-
- do {
- if(access(mapsPath, F_OK) != 0)
- return -1;
- if(is_same_app_process(manager.iTarget.execPID[targetNo]) == 0)
- return -1;
-
- system(appInstallCommand);
- if(get_app_base_address(&base_address) == 1)
- break;
- sleep(0);
- }
- while(1);
- }
- return 0;
- break;
- case MSG_TIME:
- LOGI("MSG_TIME handling : %s\n", str);
- if (strlen(manager.appPath) > 0)
- {
- is_pie_build = is_app_built_pie();
- get_app_base_address(&base_address);
- app_type = get_app_type();
- bufAppInstall[0] = '\0';
- get_app_install_path(bufAppInstall, APP_INSTALL_PATH_MAX);
- get_device_info(bufDeviceInfo, DA_LOG_MAX);
- if (strlen(bufAppInstall) > 0)
- {
- char buf[PATH_MAX];
- get_executable(buf, PATH_MAX);
- sprintf(log, "%d|%s`,%d`,%s`,%d`,%u`,%d`,%s/%s\n", MSG_DEVICE, bufDeviceInfo,
- manager.iTarget.execPID[targetNo], str, is_pie_build, base_address, app_type,
- bufAppInstall, get_app_name(buf));
- }
- else
- sprintf(log, "%d|%s`,%d`,%s`,%d`,%u`,%d`,\n", MSG_DEVICE, bufDeviceInfo,
- manager.iTarget.execPID[targetNo], str, is_pie_build, base_address, app_type);
- LOGI("MSG_DEVICE msg : %s\n", log);
- }
- else
- {
- sprintf(log, "%d|%d`,%s", MSG_PID, manager.iTarget.execPID[targetNo], str);
- LOGI("MSG_DEVICE msg without appname : %s\n", log);
- }
- initialized = 1;
- break;
- case MSG_TERMINATE:
- LOGI("MSG_TERMINATE handling : connectCount(%d)\n", manager.iTarget.connectCount);
- if(manager.iTarget.connectCount == 1 ){
- sprintf(log, "%d|\n", msgType);
- pthread_mutex_lock(&(manager.sendMutex));
-#ifndef LOCALTEST
- send(manager.iHost.clientSockFD, log, strlen(log), 0);
-#else
- LOGI("send to host : %s\n", log);
-#endif
- pthread_mutex_unlock(&(manager.sendMutex));
- }
- return 0;
- default:
- sprintf(log, "%d|%s\n", msgType, str);
- break;
- }
-
- if(manager.iHost.status >= DAS_TARGET_ARM_BATT_START && manager.iHost.status <= DAS_EMUL_X86_BATT_START)
- {
- LOGI("write batt log\n");
- write_batt_log(log);
- }
- else
- {
- if (manager.iHost.clientSockFD != -1)
- {
- pthread_mutex_lock(&(manager.sendMutex));
-#ifndef LOCALTEST
- send(manager.iHost.clientSockFD, log, strlen(log), 0);
-#else
- LOGI("send to host : %s\n", log);
-#endif
- pthread_mutex_unlock(&(manager.sendMutex));
- }
- }
- return 0;
-}
-
-static void* timerThread(void* data)
-{
- int err, signo;
- char buf[DA_LOG_MAX];
- sigset_t waitsigmask;
-
- LOGI("Timer thread started\n");
-
- sigemptyset(&waitsigmask);
- sigaddset(&waitsigmask, SIGALRM);
- sigaddset(&waitsigmask, SIGUSR1);
-
- while(1)
- {
- err = sigwait(&waitsigmask, &signo);
- if(err != 0)
- {
- LOGE("Failed to sigwait() in timer thread\n");
- continue;
- }
-
- if(signo == SIGALRM)
- {
- get_resource_info(buf, DA_LOG_MAX, manager.iTarget.execPID, manager.iTarget.pidCount);
- sendMsgStrToHost(buf, MSG_RESOURCE, -1);
-
- if (manager.iTarget.status < DAS_START_BEGIN || manager.iTarget.status > DAS_START_END )
- break;
- }
- else if(signo == SIGUSR1)
- {
- // end this thread
- break;
- }
- else
- {
- // not happened
- LOGE("This should not be happend in timer thread\n");
- }
- }
-
- LOGI("Timer thread ended\n");
- return NULL;
-}
-
-// return 0 if normal case
-// return minus value if critical error
-// return plus value if non-critical error
-static int timerStart()
-{
- sigset_t newsigmask;
- struct itimerval timerval;
-// char buf[DA_LOG_MAX];
-
- if(manager.timer_thread != -1) // already started
- return 1;
-
- sigemptyset(&newsigmask);
- sigaddset(&newsigmask, SIGALRM);
- sigaddset(&newsigmask, SIGUSR1);
- if(pthread_sigmask(SIG_BLOCK, &newsigmask, NULL) != 0)
- {
- LOGE("Failed to signal masking for main thread\n");
- return -1;
- }
-
- if(pthread_create(&(manager.timer_thread), NULL, timerThread, NULL) < 0)
- {
- LOGE("Failed to create timer thread\n");
- return -1;
- }
-
- timerval.it_interval.tv_sec = TIMER_INTERVAL_SEC;
- timerval.it_interval.tv_usec = TIMER_INTERVAL_USEC;
- timerval.it_value.tv_sec = TIMER_INTERVAL_SEC;
- timerval.it_value.tv_usec = TIMER_INTERVAL_USEC;
- setitimer(ITIMER_REAL, &timerval, NULL);
-
- // commected because this resource log send to host before receiving MSG_TIME message from target process
- // send initial value of profiling
-// get_resource_info(buf, DA_LOG_MAX, manager.iTarget.execPID, manager.iTarget.pidCount);
-// sendMsgStrToHost(buf, MSG_RESOURCE, -1);
-
- return 0;
-}
-
-static int timerStop()
-{
- if(manager.timer_thread != -1)
- {
-// int status;
-// sigset_t oldsigmask;
- struct itimerval stopval;
-
-// sigemptyset(&oldsigmask);
-// sigaddset(&oldsigmask, SIGALRM);
-// sigaddset(&oldsigmask, SIGUSR1);
-
- stopval.it_interval.tv_sec = 0;
- stopval.it_interval.tv_usec = 0;
- stopval.it_value.tv_sec = 0;
- stopval.it_value.tv_usec = 0;
-
- // stop timer
- setitimer(ITIMER_REAL, &stopval, NULL);
-
- pthread_kill(manager.timer_thread, SIGUSR1);
-// pthread_join(manager.timer_thread, (void**) &status);
-
-// if(sigprocmask(SIG_UNBLOCK, &oldsigmask, NULL) < 0)
-// {
-// LOGE("Failed to pthread_sigmask\n");
-// }
- manager.timer_thread = -1;
- }
- __destroySharedMemory();
-
- return 0;
-}
-
-#ifdef USE_BATT_LOG
-static void wait_for_starting()
-{
- static int chargerfd = -1;
- while (get_file_status(&chargerfd, CHARGERFD))
- {
- LOGI("wait for starting ... \n");
- __sleep(MONITORING_INTERVAL);
- }
-}
-#endif
-
-static int startProfiling(char* execpath, enum DAState status, long launchflag)
-{
- if(__createSharedMemory() < 0)
- {
- LOGE("Failed to create shared memory\n");
- return -1;
- }
-
- // set launch flag before execute application
- manager.sharedmem.pvalue->launch_flag = launchflag;
-
- // remove previous screen capture files
- remove_indir(SCREENSHOT_DIR);
- mkdir(SCREENSHOT_DIR, 0777);
-
- // execute application
- if (exec_app(execpath, get_app_type()))
- {
- manager.iTarget.status = status;
- if(timerStart() < 0)
- {
- return -1;
- }
- LOGI("Timer Started\n");
- }
- else
- {
- return -1;
- }
-
- return 0;
-}
-
-static void* terminate_thread(void* data)
-{
- int i;
- FILE* fp;
- size_t readbyte;
- char cmd[MAX_PATH_LENGTH];
- pid_t* pids = (pid_t*)data;
-
- sleep(1);
- for(i = 0; pids[i] != -2; i++)
- {
- if(pids[i] != -1)
- {
- sprintf(cmd, "ps ax | grep %d | grep -v grep", pids[i]);
- fp = popen(cmd, "r");
- if(fp)
- {
- readbyte = fread(cmd, MAX_PATH_LENGTH - 1, 1, fp);
- if(readbyte > 0) // process is still alive
- {
- sprintf(cmd, "kill -9 %d", pids[i]);
- system(cmd);
- }
- pclose(fp);
- }
- }
- }
-
- free(pids);
-
- return NULL;
-}
-
-static void terminate_all_target()
-{
- int i;
- pthread_t term_thread;
- pid_t* pids;
-
- pids = (pid_t*)malloc((manager.iTarget.pidCount + 1) * sizeof(pid_t));
-
- for (i = 0; i < manager.iTarget.pidCount; i++)
- {
- pids[i] = manager.iTarget.execPID[i];
- if(manager.iTarget.execPID[i] != -1)
- {
- LOGI("TERMINATE process(%d) by terminate_all_target()\n", manager.iTarget.execPID[i]);
- aul_terminate_pid(manager.iTarget.execPID[i]);
- manager.iTarget.execPID[i] = -1;
- }
- }
- pids[manager.iTarget.pidCount] = -2;
-
- pthread_create(&term_thread, NULL, terminate_thread, pids);
-
- manager.iTarget.pidCount = 0;
-}
-
-static void terminate_error(char* errstr, int sendtohost)
-{
- LOGE("%s, status(%d)\n", errstr, manager.iHost.status);
- manager.iHost.status = DAS_STOP;
-
- terminate_all_target();
-
- timerStop();
-
- if(sendtohost)
- sendMsgStrToHost(errstr, MSG_ERROR, -1);
-}
-
-
-// return 0 if normal case
-// return plus value if non critical error occur
-// return minus value if critical error occur
-static int hostMessageHandler(log_t * log)
-{
- int ret = 0;
- long flag = 0;
- char *barloc, *tmploc;
- char execPath[PATH_MAX];
-
- if (log == NULL)
- return 1;
-
- switch (log->type)
- {
- case MSG_START:
- LOGI("MSG_START handling : %s\n", log->data);
- if (manager.iHost.status >= DAS_START_BEGIN && manager.iHost.status <= DAS_START_END)
- {
- LOGE("MSG_START status check : %d\n", manager.iHost.status);
- return 1; // already started, then ignore this MSG_START message
- }
-
- if(log->length == 0)
- return -1; // wrong message format
-
- // parsing for host start status
- tmploc = log->data;
- barloc = strchr(tmploc, '|');
- if(barloc != NULL)
- {
- manager.iHost.status = 0;
- while(tmploc < barloc)
- {
- manager.iHost.status = (manager.iHost.status * 2) + (*tmploc - '0');
- tmploc++;
- }
- manager.iHost.status += 1;
-
- if(manager.iHost.status < DAS_START_BEGIN || manager.iHost.status > DAS_START_END)
- {
- manager.iHost.status = DAS_EMUL_X86_START;
- ret = 1;
- }
- }
- else
- {
- return -1; // wrong message format
- }
-
- // parsing for target launch option flag
- tmploc = barloc + 1;
- barloc = strchr(tmploc, '|');
- if(barloc != NULL)
- {
- while(tmploc < barloc)
- {
- flag = (flag * 2) + (*tmploc - '0');
- tmploc++;
- }
- }
- else
- {
- return -1; // wrong message format
- }
-
- // parsing for application package name
- tmploc = barloc + 1;
- strcpy(manager.appPath, tmploc);
-
-#ifdef USE_BATT_LOG
- if(manager.iHost.status == DAS_EMUL_ARM_BATT_START ||
- manager.iHost.status == DAS_EMUL_X86_BATT_START)
- wait_for_starting();
-#endif
-
- get_executable(execPath, PATH_MAX); // get exact app executable file name
-#if RUN_APP_LOADER
- kill_app(manager.appPath);
-#else
- // use execPath instead of manager.appPath
- kill_app(execPath);
-#endif
- sleep(0);
-
- LOGI("executable app path %s\n", manager.appPath);
-
- {
- char appInstallCommand[PATH_MAX];
-
- //save app install path
- mkdir(DA_INSTALL_DIR, 0775);
- sprintf(appInstallCommand,
- "%s -Wwi %s | grep DW_AT_comp_dir > %s", DA_READELF_PATH,
- execPath, DA_INSTALL_PATH);
- LOGI("appInstallCommand %s\n", appInstallCommand);
- system(appInstallCommand);
-
- sprintf(appInstallCommand,
- "%s -h %s | grep Type | cut -d\" \" -f33 > %s", DA_READELF_PATH,
- execPath, DA_BUILD_OPTION);
- LOGI("appInstallCommand %s\n", appInstallCommand);
- system(appInstallCommand);
-
-#if RUN_APP_LOADER
- if(startProfiling(manager.appPath, manager.iHost.status, flag) < 0)
-#else
- // use execPath instead of manager.appPath
- if(startProfiling(execPath, manager.iHost.status, flag) < 0)
-#endif
- {
- terminate_error("Cannot start profiling", 1);
- return -1;
- }
- }
- break;
- case MSG_STOP:
- LOGI("MSG_STOP handling\n");
- if (manager.iHost.status < DAS_START_BEGIN || manager.iHost.status > DAS_START_END)
- {
- // already stopped, not possible, ignore MSG_STOP message
- LOGE("MSG_STOP status check : %d\n", manager.iHost.status);
- return 1;
- }
-
- manager.iHost.status = DAS_STOP;
- terminate_all_target();
- timerStop();
- break;
- case MSG_OPTION:
- if(log->length > 0)
- {
- if(log->data[0] == '0')
- {
- set_launch_flag(1, 0);
- LOGI("Snapshot disabled\n");
- }
- else if(log->data[0] == '1')
- {
- set_launch_flag(1, 1);
- LOGI("Snapshot enabled\n");
- }
- else
- {
- LOGI("Wrong option message from host\n");
- }
- }
- break;
- case MSG_ISALIVE:
- sendMsgStrToHost(NULL, MSG_ALIVE, 0);
- break;
-
-#ifdef USE_BATT_LOG
- case MSG_BATT_START:
- {
- manager.iHost.status = DAS_BATT_START;
- sprintf(manager.appPath, "%s", log->data);
- create_open_batt_log(get_app_name(manager.appPath));
- wait_for_starting();
- if(startProfiling(manager.appPath, DAS_BATT_START, flag) < 0)
- {
- terminate_error("Cannot start profiling", 1);
- return -1;
- }
-// batt_start(manager.appPath);
- }
- break;
- case MSG_BATT_STOP:
- manager.iHost.status = DAS_BATT_STOP;
- timerStop();
-// batt_stop();
- break;
-#endif
-
- default:
- LOGW("Unknown msg\n");
- }
-
- return ret;
-}
-
-static int parseHostMessage(log_t* log, char* msg)
-{
- int i;
- int bfind = 0;
-
- if(log == NULL || msg == NULL)
- return 0;
-
- // Host message looks like this
- // MSG_TYPE|MSG_LENGTH|MSG_STRING
- // MSG_TYPE is always 3 digits number
- if(msg[3] == '|')
- {
- msg[3] = '\0';
- log->type = atoi(msg);
-
- if(log->type < MSG_HOST_BEGIN || log->type > MSG_HOST_END)
- return 0;
-
- msg = msg + 4;
- for(i = 0; msg[i] != '\0'; i++)
- {
- if(msg[i] == '|')
- {
- bfind = 1;
- msg[i] = '\0';
- break;
- }
- }
-
- if(bfind != 0)
- {
- int msglen;
- log->length = atoi(msg);
- msg = msg + i + 1;
- msglen = strlen(msg);
-
- if(log->length == 0)
- {
- log->data[0] = '\0';
- }
- else
- {
- if(msglen == log->length)
- strcpy(log->data, msg);
- else if(msglen > log->length) // parsing error but deal as nonerror
- strncpy(log->data, msg, log->length);
- else
- return 0; // parsing error
-
- log->data[log->length] = '\0';
- }
- }
- else
- {
- return 0; // parsing error
- }
-
- return 1; // parsing success
- }
- else
- {
- return 0; // parsing error
- }
-}
-
-#define EPOLL_SIZE 10
-#define MAX_CONNECT_SIZE 12
-#define MAX_INAROW_TARGET_MSG 10
-
-// return 0 for normal case
-static int work()
-{
- struct sockaddr_un clientAddrUn; //target
- struct sockaddr_in clientAddrIn; //host
- int i, k, find;
- ssize_t recvLen;
- char recvBuf[READ_BUF_MAX];
- log_t log;
-
- struct epoll_event ev, *events;
- int efd; // epoll fd
- int numevent; // number of occured events
-
- // initialize epoll event pool
- events = (struct epoll_event*) malloc(sizeof(struct epoll_event) * EPOLL_SIZE);
- if(events == NULL)
- {
- LOGE("Out of memory when allocate epoll event pool\n");
- return -1;
- }
- if((efd = epoll_create(MAX_CONNECT_SIZE)) < 0)
- {
- LOGE("epoll creation error\n");
- free(events);
- return -1;
- }
-
- // add server sockets to epoll event pool
- ev.events = EPOLLIN;
- ev.data.fd = manager.iHost.serverSockFD;
- if(epoll_ctl(efd, EPOLL_CTL_ADD, manager.iHost.serverSockFD, &ev) < 0)
- {
- LOGE("Host server socket epoll_ctl error\n");
- free(events);
- close(efd);
- return -1;
- }
- ev.events = EPOLLIN;
- ev.data.fd = manager.iTarget.serverSockFD;
- if(epoll_ctl(efd, EPOLL_CTL_ADD, manager.iTarget.serverSockFD, &ev) < 0)
- {
- LOGE("Target server socket epoll_ctl error\n");
- free(events);
- close(efd);
- return -1;
- }
-
- // handler loop
- while (1)
- {
- numevent = epoll_wait(efd, events, EPOLL_SIZE, -1);
- if(numevent <= 0)
- {
- LOGE("Failed to epoll_wait : num of event(%d), errno(%d)\n", numevent, errno);
- continue;
- }
-
- for(i = 0; i < numevent; i++)
- {
- find = 0;
- for(k = 0; k < manager.iTarget.connectCount; k++)
- {
- if(events[i].data.fd == manager.iTarget.clientSockFD[k])
- {
- // read from target process
- recvLen = recv(manager.iTarget.clientSockFD[k], &log,
- sizeof(log.type) + sizeof(log.length), 0);
-
- // send to host
- if (recvLen > 0)
- {
- int count = 0;
- do {
- if (log.length > 0)
- recv(manager.iTarget.clientSockFD[k], log.data, log.length, 0);
- log.data[log.length] = '\0';
- if(log.type == 5) // MSG_LOG
- {
- switch(log.data[0])
- {
- case '2': // UI control creation log
- case '3': // UI event log
- case '6': // UI lifecycle log
- case '7': // screnshot log
- case '8': // scene transition log
- LOGI("%dclass|%s\n", log.data[0] - '0', log.data);
- break;
- default:
- break;
- }
- }
- else if(log.type == 6) // MSG_IMAGE
- {
- LOGI("MSG_IMAGE received\n");
- }
- else // not MSG_LOG and not MSG_IMAGE
- {
- LOGI("Extra MSG TYPE (%d|%d|%s)\n", log.type, log.length, log.data);
- }
- sendMsgStrToHost(log.data, log.type, k);
- if(count++ > MAX_INAROW_TARGET_MSG)
- break;
- } while ((recvLen = recv(manager.iTarget.clientSockFD[k],
- &log, sizeof(log.type) + sizeof(log.length), MSG_DONTWAIT)) > 0);
- }
-
- // close request from target client socket
- if(recvLen == 0)
- {
- LOGI("target close = %d(total %d)\n", manager.iTarget.clientSockFD[k], manager.iTarget.connectCount - 1);
- if(epoll_ctl(efd, EPOLL_CTL_DEL, manager.iTarget.clientSockFD[k], NULL) < 0)
- {
- LOGE("Failed to epoll_ctl delete fd from event poll\n");
- }
- close(manager.iTarget.clientSockFD[k]);
- LOGI("Terminate %dth pid(%d)\n", k, manager.iTarget.execPID[k]);
- // consume that target process is already in terminating phase
-// _terminate_pid(manager.iTarget.execPID[k]);
- manager.iTarget.connectCount--;
- if(manager.iTarget.execPID[k] != -1)
- manager.iTarget.pidCount--;
-// assert(manager.iTarget.connectCount == manager.iTarget.pidCount);
- if (manager.iTarget.connectCount == 0) // all target client are closed
- {
- manager.iTarget.status = DAS_TERMINATE;
-
- LOGI("Exit daemon process\n");
- manager.iTarget.clientSockFD[k] = -1;
- manager.iTarget.execPID[k] = -1;
- timerStop();
- free(events);
- close(efd);
- return 0;
- }
- else
- {
- manager.iTarget.clientSockFD[k] = manager.iTarget.clientSockFD[manager.iTarget.connectCount];
- manager.iTarget.clientSockFD[manager.iTarget.connectCount] = -1;
- manager.iTarget.execPID[k] = manager.iTarget.execPID[manager.iTarget.pidCount];
- manager.iTarget.execPID[manager.iTarget.pidCount] = -1;
- }
- }
-
- find = 1;
- break;
- }
- }
- if(find == 0) // this event is not from target client socket
- {
- // connect request from target
- if(events[i].data.fd == manager.iTarget.serverSockFD)
- {
- socklen_t addrlen;
- addrlen = sizeof(clientAddrUn);
- manager.iTarget.clientSockFD[manager.iTarget.connectCount] =
- accept(manager.iTarget.serverSockFD, (struct sockaddr *) &clientAddrUn, &addrlen);
-
- if(manager.iTarget.clientSockFD[manager.iTarget.connectCount] >= 0) // accept succeed
- {
- ev.events = EPOLLIN;
- ev.data.fd = manager.iTarget.clientSockFD[manager.iTarget.connectCount];
- if(epoll_ctl(efd, EPOLL_CTL_ADD, manager.iTarget.clientSockFD[manager.iTarget.connectCount], &ev) < 0)
- {
- // consider as accept fail
- LOGE("Target client epoll_ctl error\n");
- manager.iTarget.clientSockFD[manager.iTarget.connectCount] = -1;
- }
- else
- {
- LOGI("target connect = %d(total%d)\n",
- manager.iTarget.clientSockFD[manager.iTarget.connectCount], manager.iTarget.connectCount + 1);
- manager.iTarget.connectCount++;
- }
- }
- else // accept error
- {
- LOGE("Failed to accept from target server socket\n");
- }
- }
- // connect request from host
- else if(events[i].data.fd == manager.iHost.serverSockFD)
- {
- socklen_t addrlen;
- addrlen = sizeof(clientAddrIn);
- if(manager.iHost.clientSockFD != -1)
- {
- if(epoll_ctl(efd, EPOLL_CTL_DEL, manager.iHost.clientSockFD, NULL) < 0)
- {
- LOGE("Failed to delete host client socket from epoll ctrl queue\n");
- }
- close(manager.iHost.clientSockFD);
- LOGI("Host client socket is closed, fd(%d)\n", manager.iHost.clientSockFD);
- }
- manager.iHost.clientSockFD = accept(manager.iHost.serverSockFD, (struct sockaddr *) &clientAddrIn, &addrlen);
-
- if(manager.iHost.clientSockFD >= 0) // accept succeed
- {
- ev.events = EPOLLIN;
- ev.data.fd = manager.iHost.clientSockFD;
- if(epoll_ctl(efd, EPOLL_CTL_ADD, manager.iHost.clientSockFD, &ev) < 0)
- {
- // consider as accept fail
- close(manager.iHost.clientSockFD);
- manager.iHost.clientSockFD = -1;
- terminate_error("Host client epoll_ctl error", 1);
- }
- else
- {
- LOGI("host connect = %d\n", manager.iHost.clientSockFD);
- }
- }
- else // accept error
- {
- LOGE("Failed to accept from host server socket\n");
- }
- }
- // message from host
- else if(events[i].data.fd == manager.iHost.clientSockFD)
- {
- // host log format xxx|length|str
- LOGI("Host client socket selected(Message from host)\n");
- recvLen = recv(manager.iHost.clientSockFD, recvBuf, READ_BUF_MAX, 0);
-
- if (recvLen > 0)
- {
- recvBuf[recvLen] = '\0';
- LOGI("host sent this msg len(%d) str(%s)\n", recvLen, recvBuf);
- if(parseHostMessage(&log, recvBuf) == 0)
- {
- // error to parse host message
- sendMsgStrToHost("host log message is unrecognizable", MSG_ERROR, -1);
- continue;
- }
-
- //host msg command handling
- if(hostMessageHandler(&log) < 0)
- {
- terminate_error("Host message handling error", 1);
- free(events);
- close(efd);
- return 0;
- }
- }
- else // close request from HOST
- {
- // work loop quit
- if(manager.iHost.status >= DAS_START_BEGIN && manager.iHost.status <= DAS_START_END)
- {
- // host client socket end unexpectly
- terminate_error("Host client socket closed unexpectly", 0);
- }
- LOGI("host close = %d\n", manager.iHost.clientSockFD);
- free(events);
- close(efd);
- return 0;
- }
- }
- else
- {
- // never happened
- LOGW("Unknown socket fd\n");
- }
- }
- }
- }
-
- free(events);
- close(efd);
- return 0;
-}
-
-// return 0 for normal case
-static int initialize_manager()
-{
- int i;
- // make server socket
- if(__makeTargetServerSockFD() != 0)
- return -1;
- if(__makeHostServerSockFD() != 0)
- return -1;
-
- // initialize target client sockets
- for (i = 0; i < TARGET_CLIENT_COUNT_MAX; i++)
- {
- manager.iTarget.clientSockFD[i] = -1;
- manager.iTarget.execPID[i] = -1;
- }
-
- // initialize sendMutex
- pthread_mutex_init(&(manager.sendMutex), NULL);
-
- if(initialize_system_info() < 0)
- return -1;
-
- return 0;
-}
-
-static int finalize_manager()
-{
- int i;
-
- finalize_system_info();
-
- terminate_all_target();
-
- LOGI("Finalize daemon\n");
-
- // finalize target client sockets
- for (i = 0; i < TARGET_CLIENT_COUNT_MAX; i++)
- {
- if(manager.iTarget.clientSockFD[i] != -1)
- close(manager.iTarget.clientSockFD[i]);
- }
-
- // close host client socket
- if(manager.iHost.clientSockFD != -1)
- close(manager.iHost.clientSockFD);
-
- // close server socket
- if(manager.iHost.serverSockFD != -1)
- close(manager.iHost.serverSockFD);
- if(manager.iTarget.serverSockFD != -1)
- close(manager.iTarget.serverSockFD);
-
- return 0;
-}
-
-static void __attribute((destructor)) exit_func()
-{
- __destroySharedMemory();
-}
-
-int main()
-{
-#if DEBUG
- write_log();
-#endif
-
- //for terminal exit
- signal(SIGHUP, SIG_IGN);
- chdir("/");
-
- //new session reader
- setsid();
-
- // initialize manager
- if(initialize_manager() == 0)
- {
- //daemon work
- work();
-
- finalize_manager();
- return 0;
- }
- else
- return 1;
-}
*
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
*
-* Contact:
+* Contact:
*
* Jaewon Lim <jaewon81.lim@samsung.com>
* Woojin Jung <woojin2.jung@samsung.com>
* Juyoung Kim <j0.kim@samsung.com>
-*
+*
* 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
* Contributors:
* - S-Core Co., Ltd
*
-*/
+*/
-#ifndef _DA_DEBUG_H_
-#define _DA_DEBUG_H_
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if DEBUG
- #define LOGI(...) do{ fprintf(stderr, "[INF]" __VA_ARGS__ ); fflush(stderr); } while(0)
- #define LOGE(...) do{ fprintf(stderr, "[ERR]" __VA_ARGS__ ); fflush(stderr); } while(0)
- #define LOGW(...) do{ fprintf(stderr, "[WRN]" __VA_ARGS__ ); fflush(stderr); } while(0)
-#else
- #define LOGI(...) do{} while(0)
- #define LOGE(...) do{} while(0)
- #define LOGW(...) do{} while(0)
-#endif
+#include "daemon.h"
+#define DEBUG_LOGFILE "/tmp/daemonlog.da"
+#if DEBUG
+void initialize_log()
+{
+ int fd;
+ fd = open("/dev/null", O_RDONLY);
+ dup2(fd, 0);
+ fd = open(DEBUG_LOGFILE, O_WRONLY | O_CREAT | O_TRUNC, 0777);
+ if(fd < 0) {
+ fd = open("/dev/null", O_WRONLY);
+ }
+ dup2(fd, 1);
+ dup2(fd, 2);
-#ifdef __cplusplus
+ fprintf(stderr, "--- daemon starting (pid %d) ---\n", getpid());
+}
+#else
+void initialize_log()
+{
}
#endif
-#endif // _DA_DEBUG_H_
--- /dev/null
+/*
+* DA manager
+*
+* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+*
+* Contact:
+*
+* Jaewon Lim <jaewon81.lim@samsung.com>
+* Woojin Jung <woojin2.jung@samsung.com>
+* Juyoung Kim <j0.kim@samsung.com>
+*
+ * 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.
+*
+* Contributors:
+* - S-Core Co., Ltd
+*
+*/
+
+#include <stdio.h>
+#include <stdlib.h> // for realpath
+#include <string.h> // for strtok, strcpy, strncpy
+#include <limits.h> // for realpath
+
+#include <errno.h> // for errno
+#include <sys/types.h> // for accept, mkdir, opendir, readdir
+#include <sys/socket.h> // for accept
+#include <sys/stat.h> // for mkdir
+#include <sys/eventfd.h> // for eventfd
+#include <sys/epoll.h> // for epoll apis
+#include <unistd.h> // for access, sleep
+#include <attr/xattr.h> // for fsetxattr
+
+#include "daemon.h"
+#include "sys_stat.h"
+#include "utils.h"
+
+#define DA_WORK_DIR "/home/developer/sdk_tools/da/"
+#define DA_READELF_PATH "/home/developer/sdk_tools/da/readelf"
+#define SCREENSHOT_DIR "/tmp/da"
+
+#define EPOLL_SIZE 10
+#define MAX_CONNECT_SIZE 12
+
+static void terminate_error(char* errstr, int sendtohost);
+
+long long get_total_alloc_size()
+{
+ int i;
+ long long allocsize = 0;
+
+ for(i = 0; i < MAX_TARGET_COUNT; i++)
+ {
+ if(manager.target[i].socket != -1 && manager.target[i].allocmem > 0)
+ allocsize += manager.target[i].allocmem;
+ }
+ return allocsize;
+}
+
+static int getEmptyTargetSlot()
+{
+ int i;
+ for(i = 0; i < MAX_TARGET_COUNT; i++)
+ {
+ if(manager.target[i].socket == -1)
+ break;
+ }
+
+ return i;
+}
+
+static void setEmptyTargetSlot(int index)
+{
+ if(index >= 0 && index < MAX_TARGET_COUNT)
+ {
+ manager.target[index].pid = -1;
+ manager.target[index].recv_thread = -1;
+ manager.target[index].allocmem = 0;
+ manager.target[index].starttime = 0;
+ if(manager.target[index].event_fd != -1)
+ close(manager.target[index].event_fd);
+ manager.target[index].event_fd = -1;
+ if(manager.target[index].socket != -1)
+ close(manager.target[index].socket);
+ manager.target[index].socket = -1;
+ }
+}
+
+// ======================================================================================
+// send functions to host
+// ======================================================================================
+
+int sendDataToHost(msg_t* log)
+{
+ if (manager.host.data_socket != -1)
+ {
+ char logstr[DA_MSG_MAX];
+ int loglen;
+
+ if(log->length != 0)
+ loglen = sprintf(logstr, "%d|%d|%s\n", log->type, log->length + 1, log->data);
+ else
+ loglen = sprintf(logstr, "%d|%d|\n", log->type, log->length + 1);
+
+// loglen = sprintf(logstr, "%d|%s\n", log->type, log->data);
+
+ pthread_mutex_lock(&(manager.host.data_socket_mutex));
+ send(manager.host.data_socket, logstr, loglen, MSG_NOSIGNAL);
+ pthread_mutex_unlock(&(manager.host.data_socket_mutex));
+ return 0;
+ }
+ else
+ return 1;
+}
+
+// msgstr can be NULL
+static int sendACKStrToHost(enum HostMessageType resp, char* msgstr)
+{
+ if (manager.host.control_socket != -1)
+ {
+ char logstr[DA_MSG_MAX];
+ int loglen;
+
+ if(msgstr != NULL)
+ loglen = sprintf(logstr, "%d|%d|%s", (int)resp, strlen(msgstr), msgstr);
+ else
+ loglen = sprintf(logstr, "%d|0|", (int)resp);
+
+ send(manager.host.control_socket, logstr, loglen, MSG_NOSIGNAL);
+ return 0;
+ }
+ else
+ return 1;
+}
+
+static int sendACKCodeToHost(enum HostMessageType resp, int msgcode)
+{
+ if (manager.host.control_socket != -1)
+ {
+ char codestr[16];
+ char logstr[DA_MSG_MAX];
+ int loglen, codelen;
+
+ codelen = sprintf(codestr, "%d", msgcode);
+ loglen = sprintf(logstr, "%d|%d|%s", (int)resp, codelen, codestr);
+
+ send(manager.host.control_socket, logstr, loglen, MSG_NOSIGNAL);
+ return 0;
+ }
+ else
+ return 1;
+}
+
+// ========================================================================================
+// start and terminate control functions
+// ========================================================================================
+
+static int startProfiling(long launchflag)
+{
+ char execPath[PATH_MAX];
+
+ // remove previous screen capture files
+ remove_indir(SCREENSHOT_DIR);
+ mkdir(SCREENSHOT_DIR, 0777);
+
+ manager.config_flag = launchflag;
+
+#ifdef RUN_APP_LOADER
+ strcpy(execPath, manager.appPath);
+#else
+ get_executable(manager.appPath, execPath, PATH_MAX);
+#endif
+ if(exec_app(execPath, get_app_type(manager.appPath)))
+ {
+ if(samplingStart() < 0)
+ {
+ return -1;
+ }
+ LOGI("Timer Started\n");
+ }
+ else
+ return -1;
+
+ return 0;
+}
+
+// terminate single target
+// just send stop message to target process
+static void terminate_target(int index)
+{
+ ssize_t sendlen;
+ msg_t sendlog;
+ sendlog.type = MSG_STOP;
+ sendlog.length = 0;
+
+ if(manager.target[index].socket != -1)
+ {
+ // result of sending to disconnected socket is not expected
+ sendlen = send(manager.target[index].socket, &sendlog, sizeof(sendlog.type) + sizeof(sendlog.length), MSG_NOSIGNAL);
+ if(sendlen != -1)
+ {
+ LOGI("TERMINATE send exit msg (socket %d) by terminate_target()\n", manager.target[index].socket);
+ }
+ }
+}
+
+// just send stop message to all target process
+static void terminate_all_target()
+{
+ int i;
+ ssize_t sendlen;
+ msg_t sendlog;
+
+ sendlog.type = MSG_STOP;
+ sendlog.length = 0;
+
+ for (i = 0; i < MAX_TARGET_COUNT; i++)
+ {
+ if(manager.target[i].socket != -1)
+ {
+ sendlen = send(manager.target[i].socket, &sendlog, sizeof(sendlog.type) + sizeof(sendlog.length), MSG_NOSIGNAL);
+ if(sendlen != -1)
+ {
+ LOGI("TERMINATE send exit msg (socket %d) by terminate_all_target()\n", manager.target[i].socket);
+ }
+ }
+ }
+}
+
+// terminate all target and wait for threads
+static void terminate_all()
+{
+ int i;
+ terminate_all_target();
+ samplingStop();
+
+ // wait for all other thread exit
+ for(i = 0; i < MAX_TARGET_COUNT; i++)
+ {
+ if(manager.target[i].recv_thread != -1)
+ {
+ pthread_join(manager.target[i].recv_thread, NULL);
+ }
+ }
+}
+
+// terminate all profiling by critical error
+static void terminate_error(char* errstr, int sendtohost)
+{
+ msg_t log;
+
+ LOGE("TERMINATE ERROR: %s\n", errstr);
+ if(sendtohost)
+ {
+ log.type = MSG_ERROR;
+ log.length = sprintf(log.data, "%s", errstr);
+ sendDataToHost(&log);
+ }
+
+ terminate_all();
+}
+
+// ===========================================================================================
+// message parsing and handling functions
+// ===========================================================================================
+
+// return 0 for normal case
+// return negative value for error case
+static int parseHostMessage(msg_t* log, char* msg)
+{
+ int i;
+ int bfind = 0;
+ int ret = 0; // parsing success
+
+ if(log == NULL || msg == NULL)
+ return -1;
+
+ // Host message looks like this
+ // MSG_TYPE|MSG_LENGTH|MSG_STRING
+ // MSG_TYPE is always 3 digits number
+ if(msg[3] == '|')
+ {
+ msg[3] = '\0';
+ log->type = atoi(msg);
+
+ msg = msg + 4;
+ for(i = 0; msg[i] != '\0'; i++)
+ {
+ if(msg[i] == '|')
+ {
+ bfind = 1;
+ msg[i] = '\0';
+ break;
+ }
+ }
+ log->length = atoi(msg);
+
+ if(log->length == 0)
+ {
+ log->data[0] = '\0';
+ }
+ else
+ {
+ if(bfind != 0)
+ {
+ int msglen;
+ msg = msg + i + 1;
+ msglen = strlen(msg);
+
+ if(msglen == log->length)
+ {
+ strcpy(log->data, msg);
+ log->data[log->length] = '\0';
+ }
+// else if(msglen > log->length)
+// {
+// strncpy(log->data, msg, log->length);
+// log->data[log->length] = '\0';
+// }
+ else
+ {
+ ret = -1; // parsing error
+ }
+ }
+ else
+ {
+ ret = -1; // parsing error
+ }
+ }
+ }
+ else
+ {
+ ret = -1; // parsing error
+ }
+
+ return ret;
+}
+
+// return 0 if normal case
+// return plus value if non critical error occur
+// return minus value if critical error occur
+static int hostMessageHandler(msg_t* log)
+{
+ int ret = 0;
+ long flag = 0;
+ char *barloc, *tmploc;
+ char execPath[PATH_MAX];
+
+ if (log == NULL)
+ return 1;
+
+ switch (log->type)
+ {
+ case MSG_VERSION:
+ if(strcmp(PROTOCOL_VERSION, log->data) != 0)
+ {
+ sendACKCodeToHost(MSG_NOTOK, ERR_WRONG_PROTOCOL_VERSION);
+ }
+ else
+ {
+ sendACKStrToHost(MSG_OK, NULL);
+ }
+ break;
+ case MSG_START:
+ LOGI("MSG_START handling : %s\n", log->data);
+ if(log->length == 0)
+ {
+ sendACKCodeToHost(MSG_NOTOK, ERR_WRONG_MESSAGE_DATA);
+ return -1; // wrong message format
+ }
+
+ // parsing for host start status
+ tmploc = log->data;
+ barloc = strchr(tmploc, '|');
+ if(barloc == NULL)
+ {
+ sendACKCodeToHost(MSG_NOTOK, ERR_WRONG_MESSAGE_FORMAT);
+ return -1; // wrong message format
+ }
+
+ // parsing for target launch option flag
+ tmploc = barloc + 1;
+ barloc = strchr(tmploc, '|');
+ if(barloc != NULL)
+ {
+ while(tmploc < barloc)
+ {
+ flag = (flag * 10) + (*tmploc - '0');
+ tmploc++;
+ }
+ }
+ else
+ {
+ sendACKCodeToHost(MSG_NOTOK, ERR_WRONG_MESSAGE_FORMAT);
+ return -1; // wrong message format
+ }
+ LOGI("launch flag : %lx\n", flag);
+
+ // parsing for application package name
+ tmploc = barloc + 1;
+ strcpy(manager.appPath, tmploc);
+
+ get_executable(manager.appPath, execPath, PATH_MAX); // get exact app executable file name
+ LOGI("executable app path %s\n", manager.appPath);
+
+#ifdef RUN_APP_LOADER
+ kill_app(manager.appPath);
+#else
+ kill_app(execPath);
+#endif
+
+ {
+ char command[PATH_MAX];
+
+ //save app install path
+ mkdir(DA_WORK_DIR, 0775);
+ sprintf(command,
+ "%s -Wwi %s | grep DW_AT_comp_dir > %s", DA_READELF_PATH,
+ execPath, DA_INSTALL_PATH);
+ LOGI("appInstallCommand %s\n", command);
+ system(command);
+
+ sprintf(command,
+ "%s -h %s | grep Type | cut -d\" \" -f33 > %s", DA_READELF_PATH,
+ execPath, DA_BUILD_OPTION);
+ LOGI("appInstallCommand %s\n", command);
+ system(command);
+
+ if(startProfiling(flag) < 0)
+ {
+ sendACKCodeToHost(MSG_NOTOK, ERR_CANNOT_START_PROFILING);
+ return -1;
+ }
+ }
+ sendACKStrToHost(MSG_OK, NULL);
+ break;
+ case MSG_STOP:
+ LOGI("MSG_STOP handling\n");
+ sendACKStrToHost(MSG_OK, NULL);
+ terminate_all();
+ break;
+ case MSG_OPTION:
+ if(log->length > 0)
+ {
+ int i;
+ msg_t sendlog;
+ manager.config_flag = atoi(log->data);
+ sendACKStrToHost(MSG_OK, NULL);
+
+ LOGI("MSG_OPTION : str(%s), flag(%x)\n", log->data, manager.config_flag);
+
+ sendlog.type = MSG_OPTION;
+ sendlog.length = sprintf(sendlog.data, "%u", manager.config_flag);
+
+ for(i = 0; i < MAX_TARGET_COUNT; i++)
+ {
+ if(manager.target[i].socket != -1)
+ {
+ send(manager.target[i].socket, &sendlog, sizeof(sendlog.type) + sizeof(sendlog.length) + sendlog.length, MSG_NOSIGNAL);
+ }
+ }
+ }
+ else
+ {
+ sendACKCodeToHost(MSG_NOTOK, ERR_WRONG_MESSAGE_DATA);
+ ret = 1;
+ }
+ break;
+ case MSG_ISALIVE:
+ sendACKStrToHost(MSG_OK, NULL);
+ break;
+ default:
+ LOGW("Unknown msg\n");
+ sendACKCodeToHost(MSG_NOTOK, ERR_WRONG_MESSAGE_TYPE);
+ ret = 1;
+ break;
+ }
+
+ return ret;
+}
+
+// ========================================================================================
+// socket and event_fd handling functions
+// ========================================================================================
+
+// return 0 if normal case
+// return plus value if non critical error occur
+// return minus value if critical error occur
+// return -11 if all target process closed
+static int targetEventHandler(int epollfd, int index, uint64_t msg)
+{
+ msg_t log;
+
+ if(msg & EVENT_PID)
+ {
+ if(index == 0) // assume index 0 is main application process
+ {
+ int base_address;
+ char tempBuff[DA_MSG_MAX];
+ char tempBuff2[DA_MSG_MAX];
+ char tempPath[PATH_MAX];
+
+ get_executable(manager.appPath, tempPath, PATH_MAX);
+ if(realpath(tempPath, tempBuff) == NULL)
+ {
+ LOGW("Failed to get realpath of app\n");
+ strcpy(tempBuff, tempPath);
+ }
+
+ sprintf(tempPath, "/proc/%d/maps", manager.target[index].pid);
+ sprintf(tempBuff2, "cat %s | grep %s | cut -d\"-\" -f1 > %s",
+ tempPath, tempBuff, DA_BASE_ADDRESS);
+ LOGI("base address command is %s\n", tempBuff2);
+
+ do {
+ if(access(tempPath, F_OK) != 0)
+ return -1;
+ if(is_same_app_process(manager.appPath, manager.target[index].pid) == 0)
+ return -1;
+
+ system(tempBuff2);
+ if(get_app_base_address(&base_address) == 1)
+ break;
+ sleep(0);
+ } while(1);
+
+ tempPath[0] = '\0';
+ get_app_install_path(tempPath, PATH_MAX);
+ get_device_info(tempBuff, DA_MSG_MAX);
+ log.type = MSG_DEVICE;
+ if (strlen(tempPath) > 0)
+ {
+ get_executable(manager.appPath, tempBuff2, DA_MSG_MAX);
+ log.length = sprintf(log.data, "%s`,%d`,%Lu`,%d`,%u`,%d`,%s/%s", tempBuff,
+ manager.target[index].pid, manager.target[index].starttime,
+ is_app_built_pie(), base_address, get_app_type(manager.appPath),
+ tempPath, get_app_name(tempBuff2));
+ }
+ else
+ {
+ log.length = sprintf(log.data, "%s`,%d`,%Lu`,%d`,%u`,%d`,", tempBuff,
+ manager.target[index].pid, manager.target[index].starttime,
+ is_app_built_pie(), base_address, get_app_type(manager.appPath));
+ }
+
+ LOGI("%s\n", log.data);
+ }
+ else
+ {
+ log.type = MSG_PID;
+ log.length = sprintf(log.data, "%d`,%Lu", manager.target[index].pid, manager.target[index].starttime);
+ }
+
+ sendDataToHost(&log);
+ }
+
+ if(msg & EVENT_STOP || msg & EVENT_ERROR)
+ {
+ LOGI("target close, socket(%d), pid(%d) : (remaining %d target)\n",
+ manager.target[index].socket, manager.target[index].pid, manager.target_count - 1);
+
+ terminate_target(index);
+ epoll_ctl(epollfd, EPOLL_CTL_DEL, manager.target[index].event_fd, NULL);
+ setEmptyTargetSlot(index);
+ if (0 == __sync_sub_and_fetch(&manager.target_count, 1)) // all target client are closed
+ {
+ log.type = MSG_TERMINATE;
+ log.length = 0;
+ log.data[0] = '\0';
+ sendDataToHost(&log);
+ return -11;
+ }
+ }
+
+ return 0;
+}
+
+// return 0 if normal case
+// return plus value if non critical error occur
+// return minus value if critical error occur
+static int targetServerHandler(int efd)
+{
+ msg_t log;
+ struct epoll_event ev;
+
+ int index = getEmptyTargetSlot();
+ if(index == MAX_TARGET_COUNT)
+ {
+ LOGW("Max target number(8) reached, no more target can connected\n");
+ return 1;
+ }
+
+ manager.target[index].socket = accept(manager.target_server_socket, NULL, NULL);
+
+ if(manager.target[index].socket >= 0) // accept succeed
+ {
+ // set smack attribute for certification
+ fsetxattr(manager.target[index].socket, "security.SMACK64IPIN", "*", 1, 0);
+ fsetxattr(manager.target[index].socket, "security.SMACK64IPOUT", "*", 1, 0);
+
+ // send config message to target process
+ log.type = MSG_OPTION;
+ log.length = sprintf(log.data, "%u", manager.config_flag);
+ send(manager.target[index].socket, &log, sizeof(log.type) + sizeof(log.length) + log.length, MSG_NOSIGNAL);
+
+ // make event fd
+ manager.target[index].event_fd = eventfd(0, EFD_NONBLOCK);
+ if(manager.target[index].event_fd == -1)
+ {
+ // fail to make event fd
+ LOGE("fail to make event fd for socket (%d)\n", manager.target[index].socket);
+ goto TARGET_CONNECT_FAIL;
+ }
+
+ // add event fd to epoll list
+ ev.events = EPOLLIN;
+ ev.data.fd = manager.target[index].event_fd;
+ if(epoll_ctl(efd, EPOLL_CTL_ADD, manager.target[index].event_fd, &ev) < 0)
+ {
+ // fail to add event fd
+ LOGE("fail to add event fd to epoll list for socket (%d)\n", manager.target[index].socket);
+ goto TARGET_CONNECT_FAIL;
+ }
+
+ // make recv thread for target
+ if(makeRecvThread(index) != 0)
+ {
+ // fail to make recv thread
+ LOGE("fail to make recv thread for socket (%d)\n", manager.target[index].socket);
+ epoll_ctl(efd, EPOLL_CTL_DEL, manager.target[index].event_fd, NULL);
+ goto TARGET_CONNECT_FAIL;
+ }
+
+ LOGI("target connected = %d(running %d target)\n",
+ manager.target[index].socket, manager.target_count + 1);
+
+ manager.target_count++;
+ return 0;
+ }
+ else // accept error
+ {
+ LOGE("Failed to accept at target server socket\n");
+ }
+
+TARGET_CONNECT_FAIL:
+ if(manager.target_count == 0) // if this connection is main connection
+ {
+ return -1;
+ }
+ else // if this connection is not main connection then ignore process by error
+ {
+ setEmptyTargetSlot(index);
+ return 1;
+ }
+}
+
+// return 0 if normal case
+// return plus value if non critical error occur
+// return minus value if critical error occur
+static int hostServerHandler(int efd)
+{
+ static int hostserverorder = 0;
+ int csocket;
+ struct epoll_event ev;
+
+ if(hostserverorder > 1) // control and data socket connected already
+ return 1; // ignore
+
+ csocket = accept(manager.host_server_socket, NULL, NULL);
+
+ if(csocket >= 0) // accept succeed
+ {
+ ev.events = EPOLLIN;
+ ev.data.fd = csocket;
+ if(epoll_ctl(efd, EPOLL_CTL_ADD, csocket, &ev) < 0)
+ {
+ // consider as accept fail
+ LOGE("Failed to add socket fd to epoll list\n");
+ close(csocket);
+ return -1;
+ }
+
+ if(hostserverorder == 0)
+ {
+ manager.host.control_socket = csocket;
+ LOGI("host control socket connected = %d\n", csocket);
+ }
+ else
+ {
+ manager.host.data_socket = csocket;
+ LOGI("host data socket connected = %d\n", csocket);
+ }
+
+ hostserverorder++;
+ return 0;
+ }
+ else // accept error
+ {
+ LOGE("Failed to accept from host server socket\n");
+ return -1;
+ }
+}
+
+// return 0 if normal case
+// return plus value if non critical error occur
+// return minus value if critical error occur
+// return -11 if socket closed
+static int controlSocketHandler()
+{
+ ssize_t recvLen;
+ char recvBuf[DA_MSG_MAX];
+ msg_t log;
+
+ // host log format xxx|length|str
+ recvLen = recv(manager.host.control_socket, recvBuf, RECV_BUF_MAX, 0);
+
+ if (recvLen > 0)
+ {
+ recvBuf[recvLen] = '\0';
+ LOGI("host sent control msg str(%s)\n", recvBuf);
+
+ if(parseHostMessage(&log, recvBuf) < 0)
+ {
+ // error to parse host message
+ sendACKCodeToHost(MSG_NOTOK, ERR_WRONG_MESSAGE_FORMAT);
+ return 1;
+ }
+
+ // host msg command handling
+ return hostMessageHandler(&log);
+ }
+ else // close request from HOST
+ {
+ return -11;
+ }
+}
+
+// return 0 for normal case
+int daemonLoop()
+{
+ int ret = 0; // return value
+ int i, k;
+ ssize_t recvLen;
+
+ struct epoll_event ev, *events;
+ int efd; // epoll fd
+ int numevent; // number of occured events
+
+ // initialize epoll event pool
+ events = (struct epoll_event*) malloc(sizeof(struct epoll_event) * EPOLL_SIZE);
+ if(events == NULL)
+ {
+ LOGE("Out of memory when allocate epoll event pool\n");
+ ret = -1;
+ goto END_RETURN;
+ }
+ if((efd = epoll_create(MAX_CONNECT_SIZE)) < 0)
+ {
+ LOGE("epoll creation error\n");
+ ret = -1;
+ goto END_EVENT;
+ }
+
+ // add server sockets to epoll event pool
+ ev.events = EPOLLIN;
+ ev.data.fd = manager.host_server_socket;
+ if(epoll_ctl(efd, EPOLL_CTL_ADD, manager.host_server_socket, &ev) < 0)
+ {
+ LOGE("Host server socket epoll_ctl error\n");
+ ret = -1;
+ goto END_EFD;
+ }
+ ev.events = EPOLLIN;
+ ev.data.fd = manager.target_server_socket;
+ if(epoll_ctl(efd, EPOLL_CTL_ADD, manager.target_server_socket, &ev) < 0)
+ {
+ LOGE("Target server socket epoll_ctl error\n");
+ ret = -1;
+ goto END_EFD;
+ }
+
+ // handler loop
+ while (1)
+ {
+ numevent = epoll_wait(efd, events, EPOLL_SIZE, -1);
+ if(numevent <= 0)
+ {
+ LOGE("Failed to epoll_wait : num of event(%d), errno(%d)\n", numevent, errno);
+ continue;
+ }
+
+ for(i = 0; i < numevent; i++)
+ {
+ // check for request from event fd
+ for(k = 0; k < MAX_TARGET_COUNT; k++)
+ {
+ if(manager.target[k].socket != -1 &&
+ events[i].data.fd == manager.target[k].event_fd)
+ {
+ uint64_t u;
+ recvLen = read(manager.target[k].event_fd, &u, sizeof(uint64_t));
+ if(recvLen != sizeof(uint64_t))
+ {
+ // maybe closed, but ignoring is more safe then removing fd from epoll list
+ }
+ else
+ {
+ if(-11 == targetEventHandler(efd, k, u))
+ {
+ LOGI("all target process is closed\n");
+ terminate_all();
+ ret = 0;
+ goto END_EFD;
+ }
+ }
+ break;
+ }
+ }
+
+ if(k != MAX_TARGET_COUNT)
+ continue;
+
+ // connect request from target
+ if(events[i].data.fd == manager.target_server_socket)
+ {
+ if(targetServerHandler(efd) < 0) // critical error
+ {
+ terminate_error("Internal DA framework error, Please re-run the profiling.", 1);
+ ret = -1;
+ goto END_EFD;
+ }
+ }
+ // connect request from host
+ else if(events[i].data.fd == manager.host_server_socket)
+ {
+ int result = hostServerHandler(efd);
+ if(result < 0)
+ {
+ terminate_error("Internal DA framework error, Please re-run the profiling.", 1);
+ ret = -1;
+ goto END_EFD;
+ }
+ }
+ // control message from host
+ else if(events[i].data.fd == manager.host.control_socket)
+ {
+ int result = controlSocketHandler();
+ if(result == -11) // socket close
+ {
+ // close target and host socket and quit
+ LOGI("host close = %d\n", manager.host.control_socket);
+ terminate_all();
+ ret = 0;
+ goto END_EFD;
+ }
+ else if(result < 0)
+ {
+ terminate_error("Internal DA framework error, Please re-run the profiling.", 1);
+ ret = -1;
+ goto END_EFD;
+ }
+ }
+ else if(events[i].data.fd == manager.host.data_socket)
+ {
+ LOGW("host message from data socket\n");
+ }
+ // unknown socket
+ else
+ {
+ // never happened
+ LOGW("Unknown socket fd (%d)\n", events[i].data.fd);
+ }
+ }
+ }
+
+END_EFD:
+ close(efd);
+END_EVENT:
+ free(events);
+END_RETURN:
+ return ret;
+}
--- /dev/null
+/*
+* DA manager
+*
+* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+*
+* Contact:
+*
+* Jaewon Lim <jaewon81.lim@samsung.com>
+* Woojin Jung <woojin2.jung@samsung.com>
+* Juyoung Kim <j0.kim@samsung.com>
+*
+ * 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.
+*
+* Contributors:
+* - S-Core Co., Ltd
+*
+*/
+
+#include <stdint.h> // for uint64_t, int64_t
+#include <pthread.h> // for pthread_mutex_t
+
+#ifndef _DAEMON_H_
+#define _DAEMON_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PROTOCOL_VERSION "2.1"
+
+#define RUN_APP_LOADER
+
+#define MAX_TARGET_COUNT 8
+#define DA_MSG_MAX 4096
+#define RECV_BUF_MAX 4104 // = sizeof(msg_t)
+
+enum ErrorCode
+{
+ ERR_LOCKFILE_CREATE_FAILED = -101,
+ ERR_ALREADY_RUNNING = -102,
+ ERR_INITIALIZE_SYSTEM_INFO_FAILED = -103,
+ ERR_HOST_SERVER_SOCKET_CREATE_FAILED = -104,
+ ERR_TARGET_SERVER_SOCKET_CREATE_FAILED = -105,
+ ERR_WRONG_MESSAGE_FORMAT = -201,
+ ERR_WRONG_MESSAGE_TYPE = -202,
+ ERR_WRONG_MESSAGE_DATA = -203,
+ ERR_CANNOT_START_PROFILING = -204,
+ ERR_WRONG_PROTOCOL_VERSION = -205
+};
+
+enum TargetMessageType
+{
+ MSG_DEVICE = 1,
+ MSG_TIME = 2,
+ MSG_SAMPLE = 3,
+ MSG_RESOURCE = 4,
+ MSG_LOG = 5,
+ MSG_IMAGE = 6,
+ MSG_TERMINATE = 7,
+ MSG_PID = 8,
+ MSG_MSG = 9,
+ MSG_ALLOC = 10,
+ MSG_ERROR = 11
+};
+
+enum HostMessageType
+{
+ MSG_HOST_BEGIN = 100,
+ MSG_START = 100,
+ MSG_STOP = 101,
+ MSG_PAUSE = 102,
+ MSG_OPTION = 103,
+ MSG_ISALIVE = 104,
+ MSG_ALIVE = 105,
+ MSG_BATT_START = 106,
+ MSG_BATT_STOP = 107,
+ MSG_OK = 901,
+ MSG_NOTOK = 902,
+ MSG_VERSION = 999,
+ MSG_HOST_END = 999
+};
+
+enum DaOptions
+{
+ OPT_CPUMEM = 0x00000001,
+ OPT_FUNC = 0x00000002,
+ OPT_ALLOC = 0x00000004,
+ OPT_FILE = 0x00000008,
+ OPT_THREAD = 0x00000010,
+ OPT_UI = 0x00000020,
+ OPT_SNAPSHOT = 0x00000040,
+ OPT_EVENT = 0x00000080,
+ OPT_RECORD = 0x00000100
+};
+
+enum DAState
+{
+ DAS_NONE = 0,
+ DAS_START_BEGIN = 1,
+ DAS_TARGET_ARM_START = 1,
+ DAS_TARGET_X86_START = 2,
+ DAS_EMUL_ARM_START = 3,
+ DAS_EMUL_X86_START = 4,
+ DAS_TARGET_ARM_BATT_START = 5,
+ DAS_TARGET_X86_BATT_START = 6,
+ DAS_EMUL_ARM_BATT_START = 7,
+ DAS_EMUL_X86_BATT_START = 8,
+ DAS_START_END = 8,
+ DAS_STOP = 9,
+ DAS_TERMINATE = 10
+};
+
+
+#ifndef likely
+#define likely(x) __builtin_expect((x), 1)
+#define unlikely(x) __builtin_expect((x), 0)
+#endif
+
+#if DEBUG
+ #define LOGI(...) do{ fprintf(stderr, "[INF]" __VA_ARGS__ ); fflush(stderr); } while(0)
+ #define LOGE(...) do{ fprintf(stderr, "[ERR]" __VA_ARGS__ ); fflush(stderr); } while(0)
+ #define LOGW(...) do{ fprintf(stderr, "[WRN]" __VA_ARGS__ ); fflush(stderr); } while(0)
+#else
+ #define LOGI(...) do{} while(0)
+ #define LOGE(...) do{} while(0)
+ #define LOGW(...) do{} while(0)
+#endif
+
+#define EVENT_STOP 0x00000001
+#define EVENT_PID 0x00000002
+#define EVENT_ERROR 0x00000004
+
+typedef struct
+{
+ unsigned int type;
+ unsigned int length;
+ char data[DA_MSG_MAX];
+} msg_t;
+
+typedef struct
+{
+ int control_socket;
+ int data_socket;
+ pthread_mutex_t data_socket_mutex;
+} __da_host_info;
+
+typedef struct
+{
+ uint64_t starttime; // written only by recv thread
+ int64_t allocmem; // written only by recv thread
+ int pid; // written only by recv thread
+ int socket; // written only by main thread
+ pthread_t recv_thread; // written only by main thread
+ int event_fd; // for thread communication (from recv thread to main thread)
+} __da_target_info;
+
+typedef struct
+{
+ FILE* portfile;
+ int host_server_socket;
+ int target_server_socket;
+ int target_count;
+ unsigned int config_flag;
+ pthread_t sampling_thread;
+ __da_host_info host;
+ __da_target_info target[MAX_TARGET_COUNT];
+ char appPath[128]; // application executable path
+} __da_manager;
+
+extern __da_manager manager;
+
+void initialize_log();
+int daemonLoop();
+int sendDataToHost(msg_t* log);
+long long get_total_alloc_size();
+
+int makeRecvThread(int index);
+int samplingStart();
+int samplingStop();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _DAEMON_H_
--- /dev/null
+/*
+* DA manager
+*
+* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+*
+* Contact:
+*
+* Jaewon Lim <jaewon81.lim@samsung.com>
+* Woojin Jung <woojin2.jung@samsung.com>
+* Juyoung Kim <j0.kim@samsung.com>
+*
+ * 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.
+*
+* Contributors:
+* - S-Core Co., Ltd
+*
+*/
+
+#include <stdio.h> // for fopen, fprintf
+#include <stdlib.h> // for atexit
+#include <sys/types.h> // for open
+#include <sys/stat.h> // for open
+#include <sys/socket.h> // for socket
+#include <sys/un.h> // for sockaddr_un
+#include <arpa/inet.h> // for sockaddr_in, socklen_t
+
+#include <signal.h> // for signal
+#include <unistd.h> // for unlink
+#include <fcntl.h> // for open, fcntl
+#include <attr/xattr.h> // for fsetxattr
+
+#include "daemon.h"
+#include "sys_stat.h"
+
+#define SINGLETON_LOCKFILE "/tmp/lockfile.da"
+#define PORTFILE "/tmp/port.da"
+#define UDS_NAME "/tmp/da.socket"
+
+#define INIT_PORT 8001
+#define LIMIT_PORT 8100
+
+// initialize global variable
+__da_manager manager =
+{
+ NULL, -1, -1, // portfile pointer, host / target server socket
+ 0, // target count
+ 0, // config_flag
+ -1, // sampling_thread handle
+ {-1, -1, PTHREAD_MUTEX_INITIALIZER}, // host
+ {{0L, }, }, // target
+ {0, } // appPath
+};
+
+// ==============================================================================
+// util functions
+// ==============================================================================
+
+static void writeToPortfile(int code)
+{
+ if(unlikely(manager.portfile == 0))
+ return;
+
+ fprintf(manager.portfile, "%d", code);
+}
+
+// ==============================================================================
+// atexit functions
+// ==============================================================================
+
+void _close_server_socket(void)
+{
+ LOGI("close_server_socket\n");
+ // close server socket
+ if(manager.host_server_socket != -1)
+ close(manager.host_server_socket);
+ if(manager.target_server_socket != -1)
+ close(manager.target_server_socket);
+}
+
+static void _unlink_file(void)
+{
+ LOGI("unlink files\n");
+ unlink(PORTFILE);
+ unlink(SINGLETON_LOCKFILE);
+}
+
+// ===============================================================================
+// making sockets
+// ===============================================================================
+
+// return 0 for normal case
+static int makeTargetServerSocket()
+{
+ struct sockaddr_un serverAddrUn;
+
+ if(manager.target_server_socket != -1)
+ return -1; // should be never happend
+
+ // remove existed unix domain socket file
+ unlink(UDS_NAME);
+
+ if ((manager.target_server_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+ {
+ LOGE("Target server socket creation failed\n");
+ return -1;
+ }
+
+ // set smack attribute for certification
+ fsetxattr(manager.target_server_socket, "security.SMACK64IPIN", "*", 1, 0);
+ fsetxattr(manager.target_server_socket, "security.SMACK64IPOUT", "*", 1, 0);
+
+ bzero(&serverAddrUn, sizeof(serverAddrUn));
+ serverAddrUn.sun_family = AF_UNIX;
+ sprintf(serverAddrUn.sun_path, "%s", UDS_NAME);
+
+ if (-1 == bind(manager.target_server_socket, (struct sockaddr*) &serverAddrUn,
+ sizeof(serverAddrUn)))
+ {
+ LOGE("Target server socket binding failed\n");
+ return -1;
+ }
+
+ chmod(serverAddrUn.sun_path, 0777);
+
+ if (-1 == listen(manager.target_server_socket, 5))
+ {
+ LOGE("Target server socket listening failed\n");
+ return -1;
+ }
+
+ LOGI("Created TargetSock %d\n", manager.target_server_socket);
+ return 0;
+}
+
+// return port number for normal case
+// return negative value for error case
+static int makeHostServerSocket()
+{
+ struct sockaddr_in serverAddrIn;
+ int opt = 1;
+ int port;
+
+ if(manager.host_server_socket != -1)
+ return -1; // should be never happened
+
+ if ((manager.host_server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+ {
+ LOGE("Host server socket creation failed\n");
+ return -1;
+ }
+
+ setsockopt(manager.host_server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+ memset(&serverAddrIn, 0, sizeof(serverAddrIn));
+ serverAddrIn.sin_family = AF_INET;
+ serverAddrIn.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ // bind address to server socket
+ for(port = INIT_PORT; port < LIMIT_PORT; port++)
+ {
+ serverAddrIn.sin_port = htons(port);
+ if (0 == bind(manager.host_server_socket, (struct sockaddr*) &serverAddrIn, sizeof(serverAddrIn)))
+ break;
+ }
+
+ if(port == LIMIT_PORT)
+ {
+ LOGE("Host server socket binding failed\n");
+ return -1;
+ }
+
+ // enter listen state from client
+ if (-1 == listen(manager.host_server_socket, 5))
+ {
+ LOGE("Host server socket listening failed\n");
+ return -1;
+ }
+
+ LOGI("Created HostSock %d\n", manager.host_server_socket);
+ return port;
+}
+
+// ===============================================================================
+// initializing / finalizing functions
+// ===============================================================================
+
+static int singleton(void)
+{
+ struct flock fl;
+ int fd;
+
+ fd = open(SINGLETON_LOCKFILE, O_RDWR | O_CREAT, 0600);
+ if(fd < 0)
+ {
+ writeToPortfile(ERR_LOCKFILE_CREATE_FAILED);
+ LOGE("singleton lock file creation failed");
+ return -1;
+ }
+
+ fl.l_start = 0;
+ fl.l_len = 0;
+ fl.l_type = F_WRLCK;
+ fl.l_whence = SEEK_SET;
+ if(fcntl(fd, F_SETLK, &fl) < 0)
+ {
+ writeToPortfile(ERR_ALREADY_RUNNING);
+ LOGE("another instance of daemon is already running");
+ return -1;
+ }
+
+ return 0;
+}
+
+// return 0 for normal case
+static int initializeManager()
+{
+ int i;
+
+ atexit(_close_server_socket);
+
+ if(initialize_system_info() < 0)
+ {
+ writeToPortfile(ERR_INITIALIZE_SYSTEM_INFO_FAILED);
+ return -1;
+ }
+
+ // make server socket
+ if(makeTargetServerSocket() != 0)
+ {
+ writeToPortfile(ERR_TARGET_SERVER_SOCKET_CREATE_FAILED);
+ return -1;
+ }
+
+ i = makeHostServerSocket();
+ if(i < 0)
+ {
+ writeToPortfile(ERR_HOST_SERVER_SOCKET_CREATE_FAILED);
+ return -1;
+ }
+ else // host server socket creation succeed
+ {
+ writeToPortfile(i);
+ }
+
+ LOGI("SUCCESS to write port\n");
+
+ // initialize target client sockets
+ for (i = 0; i < MAX_TARGET_COUNT; i++)
+ {
+ manager.target[i].pid = -1;
+ manager.target[i].socket = -1;
+ manager.target[i].event_fd = -1;
+ manager.target[i].recv_thread = -1;
+ manager.target[i].allocmem = 0;
+ manager.target[i].starttime = 0;
+ }
+ manager.target_count = 0;
+
+ // initialize sendMutex
+ pthread_mutex_init(&(manager.host.data_socket_mutex), NULL);
+
+ return 0;
+}
+
+static int finalizeManager()
+{
+ finalize_system_info();
+
+ LOGI("Finalize daemon\n");
+
+ // close host client socket
+ if(manager.host.control_socket != -1)
+ close(manager.host.control_socket);
+ if(manager.host.data_socket != -1)
+ close(manager.host.data_socket);
+
+ return 0;
+}
+
+// main function
+int main()
+{
+ int result;
+ initialize_log();
+
+ atexit(_unlink_file);
+
+ manager.portfile = fopen(PORTFILE, "w");
+ if(manager.portfile == NULL)
+ {
+ LOGE("cannot create portfile");
+ return 1;
+ }
+
+ if(singleton() < 0)
+ return 1;
+
+ //for terminal exit
+ signal(SIGHUP, SIG_IGN);
+ chdir("/");
+
+ //new session reader
+ setsid();
+
+ // initialize manager
+ result = initializeManager();
+ fclose(manager.portfile);
+ if(result == 0)
+ {
+ //daemon work
+ daemonLoop();
+
+ finalizeManager();
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
*/
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <stdbool.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/vfs.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#endif
#include "sys_stat.h"
-#include "da_debug.h"
+#include "daemon.h"
// defines for runtime environment
#define FOR_EACH_CPU
-
#define BUFFER_MAX 1024
#define LARGE_BUFFER 512
#define MIDDLE_BUFFER 256
#define DA_PROBE_TIZEN_SONAME "da_probe_tizen.so"
#define DA_PROBE_OSP_SONAME "da_probe_osp.so"
-#ifndef likely
-#define likely(x) __builtin_expect((x), 1)
-#define unlikely(x) __builtin_expect((x), 0)
-#endif
-
enum PROCESS_DATA
{
PROCDATA_STAT,
PROCDATA_SMAPS
};
-long long get_total_alloc_size();
-
// declared by greatim
static int Hertz = 0;
static int num_of_cpu = 0;
static CPU_t* cpus = NULL;
static unsigned long probe_so_size = 0;
-// utility function
-int get_flag_num(unsigned int flag)
-{
- int i;
- for(i = 0; flag != 0; i++)
- {
- flag &= (flag - 1);
- }
- return i;
-}
-
-
-
// daemon api : get status from file
// pfd must not be null
int get_file_status(int* pfd, const char* filename)
extern "C" {
#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <dirent.h>
-#include <string.h>
-#include <pthread.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/vfs.h>
-
#define CHARGERFD "/sys/class/power_supply/battery/charge_now"
#define VOLTAGEFD "/sys/class/power_supply/battery/voltage_now"
--- /dev/null
+/*
+* DA manager
+*
+* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+*
+* Contact:
+*
+* Jaewon Lim <jaewon81.lim@samsung.com>
+* Woojin Jung <woojin2.jung@samsung.com>
+* Juyoung Kim <j0.kim@samsung.com>
+*
+ * 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.
+*
+* Contributors:
+* - S-Core Co., Ltd
+*
+*/
+
+#include <stdio.h>
+#include <stdlib.h> // for atoi, atol
+#include <string.h> // for strchr
+#include <stdint.h> // for uint64_t
+#include <sys/types.h> // for recv
+#include <sys/socket.h> // for recv
+#include <sys/time.h> // for setitimer
+#include <signal.h> // for sigemptyset, sigset_t, sigaddset, ...
+#include <unistd.h> // for write
+
+#include "daemon.h"
+#include "utils.h"
+#include "sys_stat.h"
+
+#define TIMER_INTERVAL_SEC 1
+#define TIMER_INTERVAL_USEC 0
+
+static void* recvThread(void* data)
+{
+ int index = (int)data;
+ uint64_t event;
+ ssize_t recvLen;
+ msg_t log;
+
+ // initialize target variable
+ manager.target[index].pid = -1;
+ manager.target[index].starttime = 0;
+ manager.target[index].allocmem = 0;
+
+ while(1)
+ {
+ // read from target process
+ recvLen = recv(manager.target[index].socket, &log,
+ sizeof(log.type) + sizeof(log.length), MSG_WAITALL);
+
+ if(unlikely(recvLen < sizeof(log.type) + sizeof(log.length)))
+ { // disconnect
+ event = EVENT_STOP;
+ write(manager.target[index].event_fd, &event, sizeof(uint64_t));
+ break;
+ }
+
+ // send to host
+ if (likely(log.length > 0))
+ {
+ recvLen = recv(manager.target[index].socket, log.data, log.length, MSG_WAITALL);
+ if(unlikely(recvLen != log.length)) // consume as disconnect
+ {
+ event = EVENT_STOP;
+ write(manager.target[index].event_fd, &event, sizeof(uint64_t));
+ break;
+ }
+ }
+
+ log.data[log.length] = '\0';
+ if(log.type == MSG_ALLOC)
+ {
+ manager.target[index].allocmem = str_to_int64(log.data);
+ continue; // don't send to host
+ }
+ else if(log.type == MSG_PID)
+ {
+ LOGI("MSG_PID arrived : %s\n", log.data);
+
+ // only when first MSG_PID is arrived
+ if(manager.target[index].pid == -1)
+ {
+ char* barloc;
+ barloc = strchr(log.data, '|');
+ if(barloc == NULL)
+ {
+ // MSG_PID parsing error
+ // send error message to host
+ log.type = MSG_ERROR;
+ log.length = sprintf(log.data, "Process id information of target application is not correct.");
+ sendDataToHost(&log);
+
+ // send stop message to main thread
+ event = EVENT_STOP;
+ write(manager.target[index].event_fd, &event, sizeof(uint64_t));
+ break;
+ }
+ barloc[0] = '\0';
+ barloc++;
+
+ manager.target[index].pid = atoi(log.data);
+ manager.target[index].starttime = str_to_uint64(barloc);
+
+ event = EVENT_PID;
+ write(manager.target[index].event_fd, &event, sizeof(uint64_t));
+ }
+ continue; // don't send to host
+ }
+ else if(log.type == MSG_TERMINATE)
+ {
+ // send stop message to main thread
+ event = EVENT_STOP;
+ write(manager.target[index].event_fd, &event, sizeof(uint64_t));
+ break;
+ }
+#ifdef PRINT_TARGET_LOG
+ else if(log.type == MSG_LOG)
+ {
+ switch(log.data[0])
+ {
+ case '2': // UI control creation log
+ case '3': // UI event log
+ case '6': // UI lifecycle log
+ case '7': // screenshot log
+ case '8': // scene transition log
+ LOGI("%dclass|%s\n", log.data[0] - '0', log.data);
+ break;
+ default:
+ break;
+ }
+ }
+ else if(log.type == MSG_IMAGE)
+ {
+ LOGI("MSG_IMAGE received\n");
+ }
+ else // not MSG_LOG and not MSG_IMAGE
+ {
+ LOGI("Extra MSG TYPE (%d|%d|%s)\n", log.type, log.length, log.data);
+ }
+#endif
+
+ // any message before MSG_PID message arrived did not be sent to host
+ if(manager.target[index].pid != -1)
+ sendDataToHost(&log);
+ }
+
+ manager.target[index].recv_thread = -1;
+ return NULL;
+}
+
+int makeRecvThread(int index)
+{
+ if(manager.target[index].socket == -1)
+ return -1;
+
+ if(pthread_create(&(manager.target[index].recv_thread), NULL, recvThread, (void*)index) < 0)
+ {
+ LOGE("Failed to create recv thread for socket (%d)\n", manager.target[index].socket);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void* samplingThread(void* data)
+{
+ int err, signo, i;
+ int pidarray[MAX_TARGET_COUNT];
+ int pidcount;
+ sigset_t waitsigmask;
+ msg_t log;
+
+ LOGI("sampling thread started\n");
+
+ sigemptyset(&waitsigmask);
+ sigaddset(&waitsigmask, SIGALRM);
+ sigaddset(&waitsigmask, SIGUSR1);
+
+ while(1)
+ {
+ err = sigwait(&waitsigmask, &signo);
+ if(err != 0)
+ {
+ LOGE("Failed to sigwait() in sampling thread\n");
+ continue;
+ }
+
+ if(signo == SIGALRM)
+ {
+ pidcount = 0;
+ for(i = 0; i < MAX_TARGET_COUNT; i++)
+ {
+ if(manager.target[i].socket != -1 && manager.target[i].pid != -1)
+ pidarray[pidcount++] = manager.target[i].pid;
+ }
+
+ log.length = get_resource_info(log.data, DA_MSG_MAX, pidarray, pidcount);
+ if(log.length >= 0)
+ {
+ log.type = MSG_RESOURCE;
+ sendDataToHost(&log);
+ }
+ }
+ else if(signo == SIGUSR1)
+ {
+ // end this thread
+ break;
+ }
+ else
+ {
+ // not happened
+ LOGE("This should not be happend in sampling thread\n");
+ }
+ }
+
+ LOGI("sampling thread ended\n");
+ return NULL;
+}
+
+
+// return 0 if normal case
+// return minus value if critical error
+// return plus value if non-critical error
+int samplingStart()
+{
+ sigset_t newsigmask;
+ struct itimerval timerval;
+
+ if(manager.sampling_thread != -1) // already started
+ return 1;
+
+ sigemptyset(&newsigmask);
+ sigaddset(&newsigmask, SIGALRM);
+ sigaddset(&newsigmask, SIGUSR1);
+ if(pthread_sigmask(SIG_BLOCK, &newsigmask, NULL) != 0)
+ {
+ LOGE("Failed to signal masking for main thread\n");
+ return -1;
+ }
+
+ if(pthread_create(&(manager.sampling_thread), NULL, samplingThread, NULL) < 0)
+ {
+ LOGE("Failed to create sampling thread\n");
+ return -1;
+ }
+
+ timerval.it_interval.tv_sec = TIMER_INTERVAL_SEC;
+ timerval.it_interval.tv_usec = TIMER_INTERVAL_USEC;
+ timerval.it_value.tv_sec = TIMER_INTERVAL_SEC;
+ timerval.it_value.tv_usec = TIMER_INTERVAL_USEC;
+ setitimer(ITIMER_REAL, &timerval, NULL);
+
+ return 0;
+}
+
+int samplingStop()
+{
+ if(manager.sampling_thread != -1)
+ {
+ struct itimerval stopval;
+// int status;
+// sigset_t oldsigmask;
+// sigemptyset(&oldsigmask);
+// sigaddset(&oldsigmask, SIGALRM);
+// sigaddset(&oldsigmask, SIGUSR1);
+
+ // stop timer
+ stopval.it_interval.tv_sec = 0;
+ stopval.it_interval.tv_usec = 0;
+ stopval.it_value.tv_sec = 0;
+ stopval.it_value.tv_usec = 0;
+ setitimer(ITIMER_REAL, &stopval, NULL);
+
+ pthread_kill(manager.sampling_thread, SIGUSR1);
+ pthread_join(manager.sampling_thread, NULL);
+
+ // this code commented because this phrase occurs an error
+// if(sigprocmask(SIG_UNBLOCK, &oldsigmask, NULL) < 0)
+// {
+// LOGE("Failed to pthread_sigmask\n");
+// }
+ manager.sampling_thread = -1;
+ }
+
+ return 0;
+}
*
*/
+#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
#include <pthread.h>
+#include <unistd.h> // for unlink
+#include <dirent.h> // for opendir, readdir
+#include <sys/types.h> // for open
+#include <sys/stat.h> // for open
+#include <fcntl.h> // for open
+#include <grp.h> // for setgroups
+
+#include "daemon.h"
#include "utils.h"
-#include "da_debug.h"
-#define BUFFER_MAX 1024
+#define BUFFER_MAX 1024
+#define APP_GROUPS_MAX 100
+#define APP_GROUP_LIST "/usr/share/privilege-control/app_group_list"
+#define SELF_LABEL_FILE "/proc/self/attr/current"
+#define SMACK_LABEL_LEN 255
+#define SID_APP 5000
-static int file_fd = -1;
+#define APPDIR1 "/opt/apps/"
+#define APPDIR2 "/opt/usr/apps/"
-static pthread_mutex_t write_mutex;
+uint64_t str_to_uint64(char* str)
+{
+ uint64_t res = 0;
+
+ if(str != NULL)
+ {
+ while(*str >= '0' && *str <= '9')
+ {
+ res = res * 10 + (*str - '0');
+ str++;
+ }
+ }
-// get application name from executable binary path
-char* get_app_name(char* binary_path)
+ return res;
+}
+
+int64_t str_to_int64(char* str)
{
- char* pos;
+ int64_t res = 0;
+ int64_t factor = 1;
+
+ if(str != NULL)
+ {
+ if(*str == '-')
+ {
+ factor = -1;
+ str++;
+ }
+ else if(*str == '+')
+ {
+ factor = 1;
+ str++;
+ }
- pos = strrchr(binary_path, '/');
- if(pos != NULL)
- pos++;
+ while(*str >= '0' && *str <= '9')
+ {
+ res = res * 10 + (*str - '0');
+ str++;
+ }
+ }
- return pos;
+ return (res * factor);
}
-// execute applcation with executable binary path
-// return 0 to fail to execute
-// return 1 to succeed to execute
-int exec_app(const char* exec_path, int app_type)
+int read_line(const int fd, char* ptr, const unsigned int maxlen)
{
- pid_t pid;
- char command[PATH_MAX];
+ unsigned int n = 0;
+ char c[2];
+ int rc;
- if (exec_path == NULL || strlen(exec_path) <= 0)
+ while(n != maxlen)
{
- LOGE("Executable path is not correct\n");
- return 0;
+ if((rc = read(fd, c, 1)) != 1)
+ return -1; // eof or read err
+
+ if(*c == '\n')
+ {
+ ptr[n] = 0;
+ return n;
+ }
+ ptr[n++] = *c;
}
+ return -1; // no space
+}
- if (( pid = fork()) < 0) // fork error
- return 0;
+int smack_set_label_for_self(const char *label)
+{
+ int len;
+ int fd;
+ int ret;
- else if(pid > 0)
- return 1; // exit parent process with successness
+ len = strnlen(label, SMACK_LABEL_LEN + 1);
+ if (len > SMACK_LABEL_LEN)
+ return -1;
+
+ fd = open(SELF_LABEL_FILE, O_WRONLY);
+ if (fd < 0)
+ return -1;
- sprintf(command, "%s %s", DA_PRELOAD(app_type), exec_path);
- LOGI("launch app path is %s, executable path is %s\n", LAUNCH_APP_PATH, exec_path);
- execl(SHELL_CMD, SHELL_CMD, "-c", command, NULL);
+ ret = write(fd, label, len);
+ close(fd);
- return 1;
+ return (ret < 0) ? -1 : 0;
}
-#ifdef USE_LAUNCH_PAD
-// execute application by launch pad
-// return 0 to fail to execute
-// return 1 to succeed to execute
-int exec_app_by_launchpad(const char* pkg_name)
+void set_appuser_groups(void)
{
- pid_t pid;
-
- if (pkg_name == NULL || strlen(pkg_name) <= 0)
+ int fd = 0;
+ char buffer[5];
+ gid_t t_gid = -1;
+ gid_t groups[APP_GROUPS_MAX] = {0, };
+ int cnt = 0;
+
+ // groups[cnt++] = SID_DEVELOPER;
+ fd = open(APP_GROUP_LIST, O_RDONLY);
+ if(fd < 0)
{
- LOGE("Package name is not correct\n");
- return 0;
+ LOGE("cannot get app's group lists from %s", APP_GROUP_LIST);
+ return;
}
- if (( pid = fork()) < 0) // fork error
- return 0;
+ for(;;)
+ {
+ if(read_line(fd, buffer, sizeof buffer) < 0)
+ {
+ break;
+ }
- else if(pid > 0)
- return 1; // exit parent process with successness
+ t_gid = strtoul(buffer, 0, 10);
+ errno = 0;
+ if(errno != 0)
+ {
+ LOGE("cannot change string to integer: [%s]\n", buffer);
+ continue;
+ }
- LOGI("launch app path is %s, pkg name is %s\n", LAUNCH_APP_PATH, pkg_name);
- execl(LAUNCH_APP_PATH, LAUNCH_APP_NAME, pkg_name, DA_PRELOAD_EXEC, NULL);
+ if(t_gid)
+ {
+ if(cnt < APP_GROUPS_MAX)
+ {
+ groups[cnt++] = t_gid;
+ }
+ else
+ {
+ LOGE("cannot add groups more than %d", APP_GROUPS_MAX);
+ break;
+ }
+ }
+ }
- return 1;
+ if(cnt > 0)
+ {
+ if(setgroups(sizeof(groups) / sizeof(groups[0]), groups) != 0)
+ {
+ fprintf(stderr, "set groups failed errno: %d\n", errno);
+ exit(1);
+ }
+ }
}
-#endif
-#if 0
-void kill_app(const char* binary_path) // fork version
+int get_smack_label(const char* execpath, char* buffer, int buflen)
{
- pid_t pid;
- pid_t pkg_pid;
- char command[PATH_MAX];
+ int i, ret = 0;
+ char* temp;
+ if(strncmp(execpath, APPDIR1, strlen(APPDIR1)) == 0)
+ {
+ execpath = execpath + strlen(APPDIR1);
+ temp = strchr(execpath, '/');
+ for(i = 0; i < strlen(execpath) ; i++)
+ {
+ if(execpath + i == temp)
+ break;
+ buffer[i] = execpath[i];
+ }
+ buffer[i] = '\0';
+ }
+ else if(strncmp(execpath, APPDIR2, strlen(APPDIR2)) == 0)
+ {
+ execpath = execpath + strlen(APPDIR2);
+ temp = strchr(execpath, '/');
+ for(i = 0; i < strlen(execpath) ; i++)
+ {
+ if(execpath + i == temp)
+ break;
+ buffer[i] = execpath[i];
+ }
+ buffer[i] = '\0';
+ }
+ else
+ {
+ ret = -1;
+ }
- if (( pid = fork()) < 0)
- return;
+ return ret;
+}
- //exit parent process
- else if(pid > 0)
- return;
-
- pkg_pid = find_pid_from_path(binary_path);
+// return 0 if succeed
+// return -1 if error occured
+int remove_indir(const char *dirname)
+{
+ DIR *dir;
+ struct dirent *entry;
+ char path[PATH_MAX];
- if(pkg_pid > 0)
+ dir = opendir(dirname);
+ if(dir == NULL)
{
- sprintf(command, "kill -9 %d", pkg_pid);
- LOGI(" : %s\n", command);
- execl(SHELL_CMD, SHELL_CMD, "-c", command, NULL);
+ return -1;
}
- else
+
+ while((entry = readdir(dir)) != NULL)
{
- exit(0);
+ if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
+ {
+ snprintf(path, (size_t) PATH_MAX, "%s/%s", dirname, entry->d_name);
+ if (entry->d_type != DT_DIR) // file
+ {
+ unlink(path);
+ }
+ else { } // directory
+ }
}
+ closedir(dir);
+
+ return 0;
}
-#else
-void kill_app(const char* binary_path) // non fork version
+
+// get application name from executable binary path
+char* get_app_name(char* binary_path)
{
- pid_t pkg_pid;
+ char* pos;
+
+ pos = strrchr(binary_path, '/');
+ if(pos != NULL)
+ pos++;
+
+ return pos;
+}
+
+// execute applcation with executable binary path
+// return 0 to fail to execute
+// return 1 to succeed to execute
+int exec_app(const char* exec_path, int app_type)
+{
+ pid_t pid;
char command[PATH_MAX];
+ char appid[SMACK_LABEL_LEN];
- pkg_pid = find_pid_from_path(binary_path);
+ if (exec_path == NULL || strlen(exec_path) <= 0)
+ {
+ LOGE("Executable path is not correct\n");
+ return 0;
+ }
- if(pkg_pid > 0)
+ if (( pid = fork()) < 0) // fork error
+ return 0;
+
+ else if(pid > 0)
+ return 1; // exit parent process with successness
+
+ if(get_smack_label(exec_path, appid, SMACK_LABEL_LEN) < 0)
{
- sprintf(command, "kill -9 %d", pkg_pid);
- LOGI("kill app : %s\n", command);
- system(command);
+ LOGE("failed to get smack label\n");
+ return 0;
+ }
+ else
+ {
+ LOGI("smack lable is %s\n", appid);
+ if(smack_set_label_for_self(appid) < 0)
+ {
+ LOGE("failed to set label for self\n");
+ }
+
+ set_appuser_groups();
+ if(setgid(SID_APP) < 0)
+ {
+ LOGE("failed to setgid\n");
+ }
+ if(setuid(SID_APP) < 0)
+ {
+ LOGE("failed to setuid\n");
+ }
+ sprintf(command, "%s %s", DA_PRELOAD(app_type), exec_path);
+ LOGI("launch app path is %s, executable path is %s\n", LAUNCH_APP_PATH, exec_path);
+ execl(SHELL_CMD, SHELL_CMD, "-c", command, NULL);
+ return 1;
}
}
-#endif
// find process id from executable binary path
pid_t find_pid_from_path(const char* path)
return status;
}
-static void mkdirs()
+void kill_app(const char* binary_path)
{
- mkdir("/home/developer/sdk_tools/da", 0775);
- mkdir("/home/developer/sdk_tools/da/battery", 0775);
+ pid_t pkg_pid;
+ char command[PATH_MAX];
+
+ pkg_pid = find_pid_from_path(binary_path);
+ if(pkg_pid > 0)
+ {
+ sprintf(command, "kill -9 %d", pkg_pid);
+ system(command);
+ }
}
-int create_open_batt_log(const char* app_name)
+int get_app_type(char* appPath)
{
- char log_path[PATH_MAX];
+ int fd;
+ char buf[BUFFER_MAX];
- pthread_mutex_init(&write_mutex, NULL);
- sprintf(log_path, "%s%s", BATT_LOG_FILE, app_name);
-
- if ((file_fd = open(log_path, O_WRONLY|O_CREAT|O_TRUNC)) == -1)
+ sprintf(buf, "%s.exe", appPath);
+ fd = open(buf, O_RDONLY);
+ if(fd != -1)
{
- mkdirs();
- if ((file_fd = open(log_path, O_WRONLY|O_CREAT|O_TRUNC)) == -1)
- {
- LOGE("Failed to open batt log file\n");
- return 0;
- }
+ close(fd);
+ return APP_TYPE_OSP;
+ }
+ else
+ {
+ return APP_TYPE_TIZEN;
}
-
- return file_fd;
}
-int get_batt_fd()
+int get_executable(char* appPath, char* buf, int buflen)
{
- return file_fd;
+ int fd;
+
+ sprintf(buf, "%s.exe", appPath);
+ fd = open(buf, O_RDONLY);
+ if(fd != -1)
+ {
+ close(fd);
+ }
+ else
+ {
+ strcpy(buf, appPath);
+ }
+ return 0;
}
-int write_batt_log(const char* msg)
+int get_app_install_path(char *strAppInstall, int length)
{
- int length = -1;
+ FILE *fp;
+ char buf[BUFFER_MAX];
+ char *p;
+ int i;
- if (file_fd == -1 )
+ if ((fp = fopen(DA_INSTALL_PATH, "r")) == NULL)
{
+ LOGE("Failed to open %s\n", DA_INSTALL_PATH);
return -1;
}
- pthread_mutex_lock(&write_mutex);
+ /*ex : <15> DW_AT_comp_dir : (indirect string, offset: 0x25f): /home/yt/workspace/templatetest/Debug-Tizen-Emulator */
+ while (fgets(buf, BUFFER_MAX, fp) != NULL)
+ {
+ //name
+ p = buf;
+ for (i = 0; i < BUFFER_MAX; i++)
+ {
+ if (*p == ':')
+ break;
+ p++;
+ }
+
+ if (*p != ':')
+ break;
+ else
+ p++;
- length = write(file_fd, msg, strlen(msg));
+ //(...,offset:...)
+ for (; i < BUFFER_MAX; i++)
+ {
+ if (*p == '(')
+ {
+ while (*p != ')')
+ {
+ p++;
+ }
+ }
+ if (*p == ':')
+ break;
+ p++;
+ }
- pthread_mutex_unlock(&write_mutex);
+ //find
+ if (*p != ':')
+ break;
+ for (; i < BUFFER_MAX; i++)
+ {
+ if (*p == ':' || *p == ' ' || *p == '\t')
+ p++;
+ else
+ break;
+ }
- return length;
+ //name
+ if (strlen(p) <= length)
+ {
+ sprintf(strAppInstall, "%s", p);
+ for (i = 0; i < strlen(p); i++)
+ {
+ if (strAppInstall[i] == '\n' || strAppInstall[i] == '\t')
+ {
+ strAppInstall[i] = '\0';
+ break;
+ }
+ }
+ fclose(fp);
+ return 1;
+ }
+ }
+ fclose(fp);
+ return -1;
}
-void close_batt_fd()
+int is_app_built_pie(void)
{
- close(file_fd);
- file_fd = -1;
+ int result;
+ FILE *fp;
+ char buf[BUFFER_MAX];
+
+ if((fp = fopen(DA_BUILD_OPTION, "r")) == NULL)
+ {
+ LOGE("Failed to open %s\n", DA_BUILD_OPTION);
+ return -1;
+ }
+
+ if(fgets(buf, BUFFER_MAX, fp) != NULL)
+ {
+ if(strcmp(buf, "DYN\n") == 0)
+ result = 1;
+ else if(strcmp(buf, "EXEC\n") == 0)
+ result = 0;
+ else
+ result = -1;
+ }
+ else
+ {
+ result = -1;
+ }
+ fclose(fp);
+
+ return result;
}
-#if DEBUG
-void write_log()
+int get_app_base_address(int *baseAddress)
{
- int fd;
+ int res;
+ FILE *fp;
+ char buf[BUFFER_MAX];
- fd = open("/dev/null", O_RDONLY);
- dup2(fd, 0);
+ if((fp = fopen(DA_BASE_ADDRESS, "r")) == NULL)
+ {
+ LOGE("Failed to open %s\n", DA_BASE_ADDRESS);
+ return -1;
+ }
- fd = open("/tmp/da_daemon.log", O_WRONLY | O_CREAT | O_TRUNC, 0640);
- if(fd < 0) {
- fd = open("/dev/null", O_WRONLY);
- }
- dup2(fd, 1);
- dup2(fd, 2);
+ if(fgets(buf, BUFFER_MAX, fp) != NULL)
+ {
+ res = sscanf(buf, "%x", baseAddress);
+ }
+ else
+ {
+ res = -1;
+ }
+ fclose(fp);
- fprintf(stderr,"--- da starting (pid %d) ---\n", getpid());
+ return res;
}
+
+int is_same_app_process(char* appPath, int pid)
+{
+ int ret = 0;
+ FILE *fp;
+ char buf[BUFFER_MAX];
+ char cmdPath[PATH_MAX];
+ char execPath[PATH_MAX];
+
+ get_executable(appPath, execPath, PATH_MAX);
+ sprintf(cmdPath, "/proc/%d/cmdline", pid);
+
+ if((fp = fopen(cmdPath, "r")) == NULL)
+ {
+ return 0;
+ }
+
+ if(fgets(buf, BUFFER_MAX, fp) != NULL)
+ {
+#ifdef RUN_APP_LOADER
+ if(strcmp(buf, appPath) == 0)
+#else
+ // use execPath instead of manager.appPath
+ if(strcmp(buf, execPath) == 0)
#endif
+ ret = 1;
+ else
+ ret = 0;
+ }
+ fclose(fp);
+ return ret;
+}
*
*/
-#ifndef _UTILS_
-#define _UTILS_
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifndef _UTILS_H_
+#define _UTILS_H_
#ifdef __cplusplus
extern "C" {
#endif
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <linux/limits.h>
-
#define LAUNCH_APP_PATH "/usr/bin/launch_app"
#define KILL_APP_PATH "/usr/bin/pkill"
#define LAUNCH_APP_NAME "launch_app"
#define BATT_LOG_FILE "/home/developer/sdk_tools/da/battery/"
#define SHELL_CMD "/bin/sh"
+#define DA_INSTALL_PATH "/home/developer/sdk_tools/da/da_install_path"
+#define DA_BUILD_OPTION "/home/developer/sdk_tools/da/da_build_option"
+#define DA_BASE_ADDRESS "/home/developer/sdk_tools/da/da_base_address"
+
enum ApplicationType
{
APP_TYPE_TIZEN = 0,
APP_TYPE_OSP = 1
};
+uint64_t str_to_uint64(char* str);
+int64_t str_to_int64(char* str);
+
+int remove_indir(const char *dirname);
+
char* get_app_name(char* binary_path);
int exec_app(const char* exec_path, int app_type);
pid_t find_pid_from_path(const char* path);
-int create_open_batt_log(const char* app_name);
-
-int get_batt_fd();
-
-int write_batt_log(const char* message);
-
-void close_batt_fd();
-
-#if DEBUG
-void write_log();
-#endif
-
+int get_app_type(char* appPath);
+int get_executable(char* appPath, char* buf, int buflen);
+int get_app_install_path(char *strAppInstall, int length);
+int is_app_built_pie(void);
+int get_app_base_address(int *baseAddress);
+int is_same_app_process(char* appPath, int pid);
#ifdef __cplusplus
}
Name: dynamic-analysis-manager
Summary: dynamic analyzer manager
-Version: 2.1.0
+Version: 2.1.1
Release: 1
Group: System/Libraries
License: Apache License, Version 2
Source: %{name}_%{version}.tar.gz
+BuildRequires: libattr-devel
BuildRequires: glib2-devel
BuildRequires: aul-devel
BuildRequires: vconf-devel