2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include <linux/limits.h>
22 #include <sys/types.h>
25 #include <bundle_internal.h>
27 #include "debugger_info.h"
29 #include "launchpad_common.h"
30 #include "launchpad_debug.h"
31 #include "launchpad_types.h"
33 #define DEBUGGER_INFO_PATH "/usr/share/aul"
35 static int debug_initialized;
36 static GList *debugger_info_list;
37 static debugger_info_h debugger_info;
38 static GList *debug_argv_list;
39 static GList *extra_argv_list;
41 int _debug_create_extra_argv(int *argc, char ***argv)
45 const char *extra_argv;
49 if (argc == NULL || argv == NULL) {
50 _E("[DEBUG] Invalid parameter");
54 if (debugger_info == NULL)
57 new_argc = g_list_length(extra_argv_list);
61 new_argv = (char **)calloc(new_argc, sizeof(char *));
62 if (new_argv == NULL) {
68 iter = g_list_first(extra_argv_list);
70 extra_argv = (const char *)iter->data;
72 new_argv[i++] = strdup(extra_argv);
74 iter = g_list_next(iter);
79 _D("[DEBUG] argc: %d, i: %d", *argc, i);
84 int _debug_create_argv(int *argc, char ***argv, bool *attach)
89 const char *debug_argv;
90 const char *attach_str;
95 if (argc == NULL || argv == NULL || attach == NULL) {
96 _E("[DEBUG] Invalid parameter");
100 if (debugger_info == NULL)
103 exe = _debugger_info_get_exe(debugger_info);
107 attach_str = _debugger_info_get_attach(debugger_info);
108 if (attach_str && strcasecmp(attach_str, "true") == 0) {
113 list = _debugger_info_get_default_opt_list(debugger_info);
114 new_argc += g_list_length(debug_argv_list) + g_list_length(list) + 1;
115 new_argv = (char **)calloc(new_argc, sizeof(char *));
116 if (new_argv == NULL) {
122 new_argv[i++] = strdup(exe);
124 iter = g_list_first(list);
126 debug_argv = (const char *)iter->data;
128 new_argv[i++] = strdup(debug_argv);
130 iter = g_list_next(iter);
133 iter = g_list_first(debug_argv_list);
135 debug_argv = (const char *)iter->data;
137 new_argv[i++] = strdup(debug_argv);
139 iter = g_list_next(iter);
144 _D("[DEBUG] argc: %d, argv[0]: %s",
145 new_argc, new_argv[LOADER_ARG_PATH]);
150 void _debug_destroy_argv(int argc, char **argv)
157 for (i = 0; i < argc; i++)
162 int _debug_get_caller_pid(bundle *kb)
167 pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
169 pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
181 static int __redirect_std_fds(bundle *kb)
189 _E("[DEBUG] Invalid parameter");
193 caller_pid = _debug_get_caller_pid(kb);
194 if (caller_pid < 0) {
195 _E("[DEBUG] Failed to get caller pid");
200 snprintf(path, sizeof(path), "/proc/%d/fd/0", caller_pid);
201 fd = open(path, O_RDONLY);
203 _E("[DEBUG] Failed to open %s [%s]", path,
204 strerror_r(errno, err_buf, sizeof(err_buf)));
211 snprintf(path, sizeof(path), "/proc/%d/fd/1", caller_pid);
212 fd = open(path, O_WRONLY);
214 _E("[DEBUG] Failed to open %s [%s]", path,
215 strerror_r(errno, err_buf, sizeof(err_buf)));
222 snprintf(path, sizeof(path), "/proc/%d/fd/2", caller_pid);
223 fd = open(path, O_WRONLY);
225 _E("[DEBUG] Failed to open %s [%s]", path,
226 strerror_r(errno, err_buf, sizeof(err_buf)));
235 static void __add_extra_argv(gpointer data, gpointer user_data)
237 const char *key = (const char *)data;
238 bundle *kb = (bundle *)user_data;
240 const char **str_arr = NULL;
244 if (key == NULL || kb == NULL)
247 _D("[DEBUG] key: %s", key);
248 if (bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) {
249 str_arr = bundle_get_str_array(kb, key, &len);
251 str = bundle_get_val(kb, key);
258 for (i = 0; i < len; i++) {
259 if (str_arr[i] == NULL)
262 extra_argv_list = g_list_append(extra_argv_list,
270 static void __add_debug_argv(gpointer data, gpointer user_data)
272 const char *key = (const char *)data;
273 bundle *kb = (bundle *)user_data;
275 const char **str_arr = NULL;
279 if (key == NULL || kb == NULL)
282 _D("[DEBUG] key: %s", key);
283 if (bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) {
284 str_arr = bundle_get_str_array(kb, key, &len);
286 str = bundle_get_val(kb, key);
293 for (i = 0; i < len; i++) {
294 if (str_arr[i] == NULL)
297 debug_argv_list = g_list_append(debug_argv_list,
305 static void __set_debug_env(gpointer data, gpointer user_data)
307 const char *key = (const char *)data;
308 bundle *kb = (bundle *)user_data;
310 const char **str_arr = NULL;
313 char buf[LINE_MAX] = {0,};
315 if (key == NULL || kb == NULL)
318 _D("[DEBUG] key: %s", key);
319 if (bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) {
320 str_arr = bundle_get_str_array(kb, key, &len);
322 str = bundle_get_val(kb, key);
332 strncat(buf, str_arr[0], sizeof(buf) - strlen(buf) - 1);
333 for (i = 1; i < len; i++) {
334 if (str_arr[i] == NULL)
337 strncat(buf, ",", sizeof(buf) - strlen(buf) - 1);
338 strncat(buf, str_arr[i], sizeof(buf) - strlen(buf) - 1);
342 _D("[DEBUG] name: %s, value: %s", key, buf);
346 static void __remove_file(gpointer data, gpointer user_data)
348 const char *file = (const char *)data;
353 _D("[DEBUG] file: %s", file);
354 if (access(file, F_OK) == 0) {
355 if (remove(file) != 0)
356 _W("[DEBUG] Failed to remove %s", file);
360 void _debug_prepare_debugger(bundle *kb)
362 const char *debugger;
369 debugger = bundle_get_val(kb, AUL_K_SDK);
370 if (debugger == NULL)
373 ret = __redirect_std_fds(kb);
375 _E("[DEBUG] Failed to redirect standard fds");
377 _D("[DEBUG] debugger: %s", debugger);
378 debugger_info = _debugger_info_find(debugger_info_list, debugger);
379 if (debugger_info == NULL)
382 list = _debugger_info_get_unlink_list(debugger_info);
383 g_list_foreach(list, __remove_file, NULL);
385 list = _debugger_info_get_extra_env_list(debugger_info);
386 g_list_foreach(list, __set_debug_env, kb);
388 list = _debugger_info_get_extra_key_list(debugger_info);
389 g_list_foreach(list, __add_debug_argv, kb);
391 list = _debugger_info_get_last_extra_key_list(debugger_info);
392 g_list_foreach(list, __add_extra_argv, kb);
395 int _debug_init(void)
397 if (debug_initialized)
400 debugger_info_list = _debugger_info_load(DEBUGGER_INFO_PATH);
401 if (debugger_info_list == NULL)
404 debug_initialized = 1;
409 void _debug_fini(void)
411 if (!debug_initialized)
414 _debugger_info_unload(debugger_info_list);