--- /dev/null
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
+
+
+
--- /dev/null
+/*
+ * CORE-LAUNCHER
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <sys/mount.h>
+#include <sys/un.h>
+#include <sys/types.h>
+
+#define CRASH_NOTI_DIR "/opt/share/crash"
+#define CRASH_NOTI_FILE "curbs.log"
+#define CRASH_NOTI_PATH CRASH_NOTI_DIR"/"CRASH_NOTI_FILE
+
+#define CRASH_CHECK_COREDUMP_NUM (10)
+#define CRASH_CHECK_SIZE (1024 * 512)
+#define CRASH_CHECK_DISK_PATH "/opt/usr"
+#define CRASH_INFO_PATH "/opt/share/crash/info"
+#define CRASH_CORE_PATH "/opt/usr/share/crash/core"
+#define CRASH_SAVE_PATH "/opt/usr/share/crash"
+#define CRASH_DUMP_PATH "/opt/usr/share/crash/dump"
+#define CRASH_REPORT_PATH "/opt/usr/share/crash/report"
+
+#define TIZEN_OPT_USR_MOUNT "/dev/mmcblk0p7"
+#define TIZEN_OPT_USR_TYPE "ext4"
+
+#define CRASH_TIME_MAX 65
+#define CRASH_INFO_EXPAND_SIZE 5
+#define CRASH_CORE_INFO_MATCH_TIMEGAP 10
+#define BUF_SIZE 1024
+#define PATH_MAX 4096
+
+#define DEBUG_CORE_LAUNCHER
+
+static ssize_t safewrite(int fd, const void *buf, size_t count)
+{
+ ssize_t n;
+ do {
+ n = write(fd, buf, count);
+ } while (n < 0 && errno == EINTR);
+ return n;
+}
+
+static bool _check_previous_coredump_num(char *check_dir, int check_num)
+{
+ DIR *dp;
+ struct dirent *de;
+ int count = 0;
+
+ if (check_dir == NULL)
+ return false;
+ if (check_num == 0)
+ return true;
+ dp = opendir(check_dir);
+ if (dp == NULL) {
+ fprintf(stderr, "error opendir %s\n", check_dir);
+ return false;
+ }
+ while (de = readdir(dp)) {
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
+ continue;
+ if (de->d_ino != 0 )
+ count++;
+ }
+ closedir(dp);
+ if (check_num < count)
+ return false;
+ else
+ return true;
+}
+/* check disk available size */
+static bool _check_disk_available(char *mount_dir, int check_size)
+{
+ struct statfs lstatfs;
+
+ if (mount_dir == NULL)
+ return false;
+ if (check_size == 0)
+ return true;
+ if (statfs(mount_dir, &lstatfs) < 0) {
+ fprintf(stderr, "can't get statfs %s\n", mount_dir);
+ return false;
+ } else {
+ if (check_size <=
+ lstatfs.f_bavail * (lstatfs.f_bsize/1024)) {
+ return true;
+ } else {
+ fprintf(stderr, "NO %d < %d\n", check_size,
+ (int)(lstatfs.f_bavail * (lstatfs.f_bsize/1024)));
+ return false;
+ }
+ }
+}
+static bool _check_crash_name_timesec(char *filename,
+ char *pid, char *timesec)
+{
+ if (filename == NULL || pid == NULL || timesec == NULL)
+ return false;
+ int pid_len = 0;
+ int times_len = 0;
+ long infotime = 0;
+ long coretime = 0;
+ long timegap = 0;
+ char tbuf[CRASH_TIME_MAX] = {0, };
+ int len = strlen(filename);
+ int i = 0;
+ for (i = 0; i < len; i++) {
+ if (filename[i] == '_') {
+ pid_len = i;
+ times_len = len - i - CRASH_INFO_EXPAND_SIZE;
+ break;
+ }
+ }
+ if (!strncmp(pid, filename, i)) {
+ strncpy(tbuf, &(filename[i+1]), times_len);
+ infotime = atol(tbuf);
+ coretime = atol(timesec);
+ timegap = labs(infotime - coretime);
+ if (timegap < CRASH_CORE_INFO_MATCH_TIMEGAP)
+ return true;
+ return false;
+ }
+ return false;
+}
+static bool check_crash_libsysinfo(char *pid, char *timesec)
+{
+ DIR *dp;
+ struct dirent *de;
+ dp = opendir(CRASH_INFO_PATH);
+ if (dp == NULL) {
+ fprintf(stderr, "error opendir %s\n", CRASH_INFO_PATH);
+ return false;
+ }
+ while (de = readdir(dp)) {
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
+ continue;
+ if (_check_crash_name_timesec(de->d_name,
+ pid, timesec) == 1) {
+ closedir(dp);
+ return true;
+ }
+ }
+ closedir(dp);
+ return false;
+}
+/*
+ * 1 2 3 4
+ * %e %t %p %s
+ */
+int main(int argc, char *argv[])
+{
+ int fd_curbs; /* for inotify */
+ int fd_coredump; /* for core dump */
+ char buf[BUF_SIZE];
+ int i;
+ bool haveinfo = false;
+ bool filesaveon = false;
+ int corefilesize = 0;
+ char corefile[PATH_MAX] = {0, }; /* corefile buf */
+ char notimsg[BUF_SIZE] = {0, }; /* crash noti message */
+ ssize_t nread;
+ const unsigned long mntflags = 0;
+#ifdef DEBUG_CORE_LAUNCHER
+ FILE *tfp;
+ char cwd[PATH_MAX];
+ snprintf(cwd, PATH_MAX,
+ "/tmp/%s_%s_%s_%s.info",
+ argv[1], argv[2], argv[3], argv[4]);
+ tfp = fopen(cwd, "w+");
+ if (tfp == NULL)
+ exit(EXIT_FAILURE);
+ fprintf(tfp, "argc=%d\n", argc);
+ for (i = 0; i < argc; i++)
+ fprintf(tfp, "argc[%d]=<%s>\n", i, argv[i]);
+#endif
+ /* check that process name is crash-worker or crash-popup, because prevent infinite called */
+ if (!strcmp(argv[1], "crash-worker") || !strcmp(argv[1], "crash-popup")) {
+#ifdef DEBUG_CORE_LAUNCHER
+ fclose(tfp);
+#endif
+ exit(EXIT_SUCCESS);
+ }
+ /* check already know crash is reported and triggerd by libsys-assert lib */
+ haveinfo = check_crash_libsysinfo(argv[3], argv[2]);
+ /* check core dump path for saving */
+ if (access(CRASH_CORE_PATH, F_OK) != 0) {
+ /* if can't access core dump path, try mount that */
+ if (mount(TIZEN_OPT_USR_MOUNT,
+ CRASH_CHECK_DISK_PATH,
+ TIZEN_OPT_USR_TYPE, mntflags, NULL) != 0)
+ sleep(2);
+ else
+ filesaveon = true;
+
+ /* one more check core dump path for saving */
+ if (access(CRASH_CORE_PATH, F_OK) != 0)
+ filesaveon = false;
+ } else
+ filesaveon = true;
+
+ /* check that disk extra sapce is available */
+ if (_check_disk_available(CRASH_CHECK_DISK_PATH,
+ CRASH_CHECK_SIZE) == true) {
+ /* check previous coredump file number,
+ because if system_server was dead,
+ crash-worker didn't working.
+ so coredump stacked an unlimited number*/
+ filesaveon = _check_previous_coredump_num(CRASH_CORE_PATH,
+ CRASH_CHECK_COREDUMP_NUM);
+ }
+
+ if (filesaveon == true) {
+ snprintf(corefile, PATH_MAX,
+ "%s/%s_%s_%s.core",
+ CRASH_CORE_PATH, argv[3], argv[4], argv[1]);
+ fd_coredump = open(corefile, O_WRONLY | O_SYNC | O_CREAT | O_TRUNC, 0644);
+ if (fd_coredump < 0) {
+ fprintf(stderr,
+ "[core-launcher]cannot open core dump file!\n");
+ } else {
+ corefilesize = 0;
+ while ((nread = read(STDIN_FILENO, buf, BUF_SIZE)) > 0) {
+ corefilesize += nread;
+ safewrite(fd_coredump, buf, nread);
+ }
+ fsync(fd_coredump);
+ close(fd_coredump);
+ }
+ }
+
+ if (haveinfo == false) {
+ /* NOTIFY CRASH */
+ fd_curbs = open(CRASH_NOTI_PATH, O_RDWR | O_APPEND);
+ if (fd_curbs < 0) {
+ fprintf(stderr,
+ "[core-launcher]cannot make %s !\n",
+ CRASH_NOTI_PATH);
+ } else {
+ snprintf(notimsg, BUF_SIZE,
+ "C|%s|%s|%s|%s|%d\n",
+ argv[1], argv[2], argv[3], argv[4], strlen(argv[1]) + strlen(argv[4]));
+ write(fd_curbs, notimsg, strlen(notimsg));
+ close(fd_curbs);
+ }
+ }
+#ifdef DEBUG_CORE_LAUNCHER
+ fprintf(tfp, "haveinfo check(%d) %s %s\n", haveinfo, argv[1], argv[2]);
+ if (filesaveon == true)
+ fprintf(tfp, "Total bytes in core dump: %d\n", corefilesize);
+ else
+ fprintf(tfp, "We didn't save core dump\n");
+ fclose(tfp);
+#endif
+ exit(EXIT_SUCCESS);
+}
+
--- /dev/null
+/*
+ * SYS-ASSERT
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <execinfo.h>
+#include <dlfcn.h>
+#include <elf.h>
+#include <fcntl.h>
+#include <ucontext.h>
+#include <signal.h>
+#include <linux/unistd.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <time.h>
+#include <syslog.h>
+/* for PR_SET_DUMPABLE */
+#include <sys/prctl.h>
+#include "sys-assert.h"
+
+#define CMDLINE_PATH "/proc/self/cmdline"
+#define DBG_DIR "/usr/lib/debug"
+#define EXE_PATH "/proc/self/exe"
+#define MAPS_PATH "/proc/self/maps"
+#define MEMINFO_PATH "/proc/meminfo"
+#define STATUS_PATH "/proc/self/status"
+
+#define CRASH_INFO_PATH "/opt/share/crash/info"
+#define CRASH_REPORT_PATH "/opt/usr/share/crash/report"
+#define CRASH_NOTI_PATH "/opt/share/crash/curbs.log"
+
+#define CRASH_CALLSTACKINFO_TITLE "Callstack Information"
+#define CRASH_CALLSTACKINFO_TITLE_E "End of Call Stack"
+#define CRASH_MAPSINFO_TITLE "Maps Information"
+#define CRASH_MAPSINFO_TITLE_E "End of Maps Information"
+#define CRASH_MEMINFO_TITLE "Memory Information"
+#define CRASH_REGISTERINFO_TITLE "Register Information"
+
+#define SUPPORT_LIBC_BACKTRACE 1
+#define USE_SYMBOL_DB 1
+#define FUNC_NAME_MAX_LEN 128
+#define FILE_LEN 255
+#define PATH_LEN (FILE_LEN + NAME_MAX)
+#define BUF_SIZE 255
+#define CALLSTACK_SIZE 100
+/* permission for open file */
+#define DIR_PERMS (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
+/* permission for open file */
+#define FILE_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
+
+int sig_to_handle[] = { /* SIGHUP, SIGINT, SIGQUIT, */ SIGILL, /*SIGTRAP, */
+ SIGABRT, /*SIGIOT, */SIGBUS,
+ SIGFPE, /*SIGKILL, SIGUSR1 */ SIGSEGV, /*SIGUSR2, */
+ SIGPIPE /*SIGXCPU,SIGXFSZ,,, */
+};
+#define NUM_SIG_TO_HANDLE \
+ ((int)(sizeof(sig_to_handle)/sizeof(sig_to_handle[0])))
+
+struct sigaction g_oldact[NUM_SIG_TO_HANDLE];
+
+static char *fgets_fd(char *s, int n, int fd)
+{
+ char c;
+ register char *cs;
+ int num = 0;
+
+ cs = s;
+ while (--n > 0 && (num = read(fd, &c, 1) > 0)) {
+ if ((*cs++ = c) == '\n')
+ break;
+ }
+ *cs = '\0';
+ return (num == 0 && cs == s) ? NULL : s;
+}
+
+/* WARNING : formatted string buffer is limited to 1024 byte */
+static int fprintf_fd(int fd, const char *fmt, ...)
+{
+ int n;
+ char buff[1024];
+ va_list args;
+
+ va_start(args, fmt);
+ n = vsnprintf(buff, 1024 - 1, fmt, args);
+ write(fd, buff, n);
+ va_end(args);
+ return n;
+}
+static char *remove_path(const char *cmd)
+{
+ char *t;
+ char *r;
+
+ t = r = (char *)cmd;
+ while (*t) {
+ if (*t == '/')
+ r = t + 1;
+ t++;
+ }
+ return r;
+}
+
+static char *get_fpath(long *value, struct addr_node *start)
+{
+ struct addr_node *t_node;
+ struct addr_node *n_node;
+
+ if (value == 0 || start == NULL)
+ return NULL;
+ t_node = start;
+ n_node = t_node->next;
+ while (t_node) {
+ if (t_node->endaddr <= value) {
+ /* next node */
+ if (n_node == NULL)
+ return NULL;
+ t_node = n_node;
+ n_node = n_node->next;
+ } else if (t_node->startaddr <= value)
+ return t_node->fpath;
+ else
+ return NULL;
+ }
+}
+
+static long *get_start_addr(long *value, struct addr_node *start)
+{
+ struct addr_node *t_node;
+ struct addr_node *n_node;
+
+ if (value == 0 || start == NULL)
+ return NULL;
+ t_node = start;
+ n_node = t_node->next;
+ while (t_node) {
+ if (t_node->endaddr <= value) {
+ /* next node */
+ if (n_node == NULL)
+ return NULL;
+ t_node = n_node;
+ n_node = n_node->next;
+ } else if (t_node->startaddr <= value)
+ return t_node->startaddr;
+ else
+ return NULL;
+ }
+}
+
+#ifdef TARGET
+/* get function symbol from elf */
+static int
+trace_symbols(void *const *array, int size, struct addr_node *start, int fd_cs)
+{
+ int cnt;
+ Dl_info info_funcs;
+#ifndef USE_SYMBOL_DB
+ int i;
+ Elf32_Ehdr elf_h;
+ Elf32_Shdr *s_headers;
+ int strtab_index = 0;
+ int symtab_index = 0;
+ int num_st = 0;
+ Elf32_Sym *symtab_entry;
+ int fd;
+ int ret;
+ char filename[256];
+#endif
+ unsigned int offset_addr;
+ unsigned int start_addr;
+ unsigned int addr;
+
+ for (cnt = 0; cnt < size; cnt++) {
+#ifndef USE_SYMBOL_DB
+ num_st = 0;
+#endif
+ /* FIXME : for walking on stack trace */
+ if (dladdr(array[cnt], &info_funcs) == 0) {
+ fprintf(stderr, "[sys-assert]dladdr returnes error!\n");
+ /* print just address */
+ fprintf_fd(fd_cs, "%2d: (%p)\n", cnt, array[cnt]);
+
+ continue;
+ }
+ start_addr = (unsigned int)get_start_addr(array[cnt], start);
+ addr = (unsigned int)array[cnt];
+/* because of launchpad,
+ * return value of dladdr when find executable is wrong.
+ * so fix dli_fname here */
+ if (info_funcs.dli_fbase == (void *)0x8000
+ &&
+ (strncmp("/opt/apps/", info_funcs.dli_fname,
+ strlen("/opt/apps/")) == 0)) {
+ fprintf(stderr,
+ "[sys-assert][%d] fname = %s, fbase = %p, sname = %s, saddr = %p\n",
+ cnt, info_funcs.dli_fname,
+ info_funcs.dli_fbase,
+ info_funcs.dli_sname, info_funcs.dli_saddr);
+ info_funcs.dli_fname = get_fpath(array[cnt], start);
+ offset_addr = addr;
+ fprintf(stderr,
+ "[sys-assert][%d] start_addr : %x, addr : %x, offset_addr : %x\n",
+ cnt, start_addr, addr, offset_addr);
+ } else {
+ offset_addr = addr - start_addr;
+ }
+ if (info_funcs.dli_sname == NULL) {
+#ifndef USE_SYMBOL_DB
+/*FIXME : get dbg file name from debuglink and search dbg file in DBG_DIR */
+ strcpy(filename, DBG_DIR);
+ strncat(filename, info_funcs.dli_fname, 128);
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ fprintf_fd(fd_cs,
+ "%2d: (%p) [%s]+%p\n",
+ cnt, array[cnt],
+ info_funcs.dli_fname, offset_addr);
+ continue;
+ }
+ ret = read(fd, &elf_h, sizeof(Elf32_Ehdr));
+ if (ret < sizeof(Elf32_Ehdr)) {
+ fprintf(stderr,
+ "[sys-assert]readnum = %d, [%s]\n",
+ ret, info_funcs.dli_fname);
+ fprintf_fd(fd_cs,
+ "%2d: (%p) [%s]+%p\n",
+ cnt, array[cnt],
+ info_funcs.dli_fname, offset_addr);
+ continue;
+ }
+ if (elf_h.e_type == ET_EXEC) {
+ info_funcs.dli_fbase = 0;
+ offset_addr = addr;
+ }
+ s_headers =
+ (Elf32_Shdr *) mmap(0,
+ elf_h.e_shnum *
+ sizeof
+ (Elf32_Shdr),
+ PROT_READ |
+ PROT_WRITE,
+ MAP_PRIVATE |
+ MAP_ANONYMOUS, -1, 0);
+ if (s_headers == NULL) {
+ fprintf(stderr, "[sys-assert]malloc failed\n");
+ fprintf_fd(fd_cs,
+ "%2d: (%p) [%s]+%p\n",
+ cnt, array[cnt],
+ info_funcs.dli_fname, offset_addr);
+ continue;
+ }
+ lseek(fd, elf_h.e_shoff, SEEK_SET);
+ if (elf_h.e_shentsize > sizeof(Elf32_Shdr))
+ return false;
+ for (i = 0; i < elf_h.e_shnum; i++) {
+ ret =
+ read(fd, &s_headers[i], elf_h.e_shentsize);
+ if (ret < elf_h.e_shentsize) {
+ fprintf(stderr,
+ "[sys-assert]read error\n");
+ munmap(s_headers,
+ elf_h.e_shnum *
+ sizeof(Elf32_Shdr));
+ return false;
+ }
+ }
+ for (i = 0; i < elf_h.e_shnum; i++) {
+/* find out .symtab Section index */
+ if (s_headers[i].sh_type == SHT_SYMTAB) {
+ symtab_index = i;
+ num_st =
+ s_headers[i].sh_size /
+ s_headers[i].sh_entsize;
+/* number of .symtab entry */
+ break;
+ }
+ }
+ /*.strtab index */
+ strtab_index = s_headers[symtab_index].sh_link;
+ symtab_entry =
+ (Elf32_Sym *)mmap(0, sizeof(Elf32_Sym) * num_st,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1,
+ 0);
+ if (symtab_entry == NULL) {
+ fprintf(stderr, "[sys-assert]malloc failed\n");
+ munmap(s_headers,
+ elf_h.e_shnum * sizeof(Elf32_Shdr));
+ return false;
+ }
+ lseek(fd, s_headers[symtab_index].sh_offset, SEEK_SET);
+ for (i = 0; i < num_st; i++) {
+ ret =
+ read(fd, &symtab_entry[i],
+ sizeof(Elf32_Sym));
+ if (ret < sizeof(Elf32_Sym)) {
+ fprintf(stderr,
+ "[sys-assert]symtab_entry[%d],\
+ num_st=%d, readnum = %d\n",
+ i, num_st, ret);
+ break;
+ }
+ if (((info_funcs.dli_fbase +
+ symtab_entry[i].st_value)
+ <= array[cnt])
+ && (array[cnt] <=
+ (info_funcs.dli_fbase +
+ symtab_entry
+ [i].st_value +
+ symtab_entry[i].st_size))) {
+ if (symtab_entry[i].st_shndx !=
+ STN_UNDEF) {
+ lseek(fd,
+ s_headers
+ [strtab_index].sh_offset +
+ symtab_entry[i].st_name,
+ SEEK_SET);
+ info_funcs.dli_sname = (void *)
+ mmap(0,
+ FUNC_NAME_MAX_LEN,
+ PROT_READ
+ |
+ PROT_WRITE,
+ MAP_PRIVATE
+ |
+ MAP_ANONYMOUS, -1, 0);
+ ret =
+ read(fd,
+ info_funcs.dli_sname,
+ FUNC_NAME_MAX_LEN);
+ info_funcs.dli_saddr =
+ info_funcs.dli_fbase +
+ symtab_entry[i].st_value;
+ }
+ break;
+ }
+ }
+ munmap(s_headers, elf_h.e_shnum * sizeof(Elf32_Shdr));
+ munmap(symtab_entry, sizeof(Elf32_Sym) * num_st);
+ close(fd);
+#endif
+ fprintf_fd(fd_cs, "%2d: (%p) [%s]+%p\n",
+ cnt, array[cnt],
+ info_funcs.dli_fname, offset_addr);
+ } else {
+
+ if (array[cnt] >= info_funcs.dli_saddr) {
+ fprintf_fd(fd_cs,
+ "%2d: %s+0x%x(%p) [%s]+%p\n",
+ cnt,
+ info_funcs.dli_sname,
+ (array[cnt] -
+ info_funcs.dli_saddr),
+ array[cnt],
+ info_funcs.dli_fname, offset_addr);
+ } else {
+ fprintf_fd(fd_cs,
+ "%2d: %s-0x%x(%p) [%s]+%p\n",
+ cnt,
+ info_funcs.dli_sname,
+ (info_funcs.dli_saddr
+ - array[cnt]),
+ array[cnt],
+ info_funcs.dli_fname, offset_addr);
+ }
+ }
+ }
+ return true;
+}
+#endif
+/* get address list from maps with print to file */
+static struct addr_node *get_addr_list_from_maps_with_print(int fd_maps, int fd)
+{
+ int result;
+ char linebuf[BUF_SIZE];
+ char addr[20];
+ char perm[5];
+ char path[PATH_LEN];
+ long *saddr;
+ long *eaddr;
+ int fpath_len;
+ struct addr_node *head = NULL;
+ struct addr_node *tail = NULL;
+ struct addr_node *t_node = NULL;
+
+ fprintf_fd(fd, "\n%s\n", CRASH_MAPSINFO_TITLE);
+
+/* parsing the maps to get executable code address */
+ while (fgets_fd(linebuf, BUF_SIZE, fd_maps) != NULL) {
+ memset(path, 0, PATH_LEN);
+ result =
+ sscanf(linebuf, "%s %s %*s %*s %*s %s ", addr, perm, path);
+ perm[4] = 0;
+/*if perm[2]=='x',addr is valid value so we have to store the address */
+#ifdef TARGET
+ if ((perm[2] == 'x' && path[0] == '/')
+ || (perm[1] == 'w' && path[0] != '/'))
+#else
+ if (strncmp(perm, "r-xp", 4) == 0)
+#endif
+ {
+ /* add addr node to list */
+ addr[8] = 0;
+ saddr = (long *)strtoul(addr, NULL, 16);
+ eaddr = (long *)strtoul(&addr[9], NULL, 16);
+ /* make node and attach to the list */
+ t_node =
+ (struct addr_node *)mmap(0,
+ sizeof
+ (struct
+ addr_node),
+ PROT_READ |
+ PROT_WRITE,
+ MAP_PRIVATE
+ | MAP_ANONYMOUS, -1, 0);
+ if (t_node == NULL) {
+ fprintf(stderr, "error : mmap\n");
+ return NULL;
+ }
+ memcpy(t_node->perm, perm, 5);
+ t_node->startaddr = saddr;
+ t_node->endaddr = eaddr;
+ t_node->fpath = NULL;
+ fpath_len = strlen(path);
+ if (fpath_len > 0) {
+ t_node->fpath =
+ (char *)mmap(0,
+ fpath_len + 1,
+ PROT_READ |
+ PROT_WRITE,
+ MAP_PRIVATE |
+ MAP_ANONYMOUS, -1, 0);
+ memset(t_node->fpath, 0, fpath_len + 1);
+ memcpy(t_node->fpath, path, fpath_len);
+ fprintf_fd(fd, "%08x %08x %s %s\n",
+ (unsigned int)t_node->startaddr,
+ (unsigned int)t_node->endaddr,
+ t_node->perm, t_node->fpath);
+ } else {
+ t_node->fpath =
+ (char *)mmap(0, 8,
+ PROT_READ |
+ PROT_WRITE,
+ MAP_PRIVATE |
+ MAP_ANONYMOUS, -1, 0);
+ memset(t_node->fpath, 0, 8);
+ memcpy(t_node->fpath, "[anony]", 7);
+ }
+ t_node->next = NULL;
+ if (head == NULL) {
+ head = t_node;
+ tail = t_node;
+ } else {
+ tail->next = t_node;
+ tail = t_node;
+ }
+ }
+ }
+ fprintf_fd(fd, "%s\n", CRASH_MAPSINFO_TITLE_E);
+ return head;
+}
+/* get address list from maps */
+static struct addr_node *get_addr_list_from_maps(int fd_maps)
+{
+ int result;
+ char linebuf[BUF_SIZE];
+ char addr[20];
+ char perm[5];
+ char path[PATH_LEN];
+ long *saddr;
+ long *eaddr;
+ int fpath_len;
+ struct addr_node *head = NULL;
+ struct addr_node *tail = NULL;
+ struct addr_node *t_node = NULL;
+
+/* parsing the maps to get executable code address */
+ while (fgets_fd(linebuf, BUF_SIZE, fd_maps) != NULL) {
+ memset(path, 0, PATH_LEN);
+ result =
+ sscanf(linebuf, "%s %s %*s %*s %*s %s ", addr, perm, path);
+ perm[4] = 0;
+/*if perm[2]=='x',addr is valid value so we have to store the address */
+#ifdef TARGET
+ if ((perm[2] == 'x' && path[0] == '/')
+ || (perm[1] == 'w' && path[0] != '/'))
+#else
+ if (strncmp(perm, "r-xp", 4) == 0)
+#endif
+ {
+ /* add addr node to list */
+ addr[8] = 0;
+ saddr = (long *)strtoul(addr, NULL, 16);
+ eaddr = (long *)strtoul(&addr[9], NULL, 16);
+ /* make node and attach to the list */
+ t_node =
+ (struct addr_node *)mmap(0,
+ sizeof
+ (struct
+ addr_node),
+ PROT_READ |
+ PROT_WRITE,
+ MAP_PRIVATE
+ | MAP_ANONYMOUS, -1, 0);
+ if (t_node == NULL) {
+ fprintf(stderr, "error : mmap\n");
+ return NULL;
+ }
+ memcpy(t_node->perm, perm, 5);
+ t_node->startaddr = saddr;
+ t_node->endaddr = eaddr;
+ t_node->fpath = NULL;
+ fpath_len = strlen(path);
+ if (fpath_len > 0) {
+ t_node->fpath =
+ (char *)mmap(0,
+ fpath_len + 1,
+ PROT_READ |
+ PROT_WRITE,
+ MAP_PRIVATE |
+ MAP_ANONYMOUS, -1, 0);
+ memset(t_node->fpath, 0, fpath_len + 1);
+ memcpy(t_node->fpath, path, fpath_len);
+ } else {
+ t_node->fpath =
+ (char *)mmap(0, 8,
+ PROT_READ |
+ PROT_WRITE,
+ MAP_PRIVATE |
+ MAP_ANONYMOUS, -1, 0);
+ memset(t_node->fpath, 0, 8);
+ memcpy(t_node->fpath, "[anony]", 7);
+ }
+
+ t_node->next = NULL;
+ if (head == NULL) {
+ head = t_node;
+ tail = t_node;
+ } else {
+ tail->next = t_node;
+ tail = t_node;
+ }
+ }
+ }
+ return head;
+}
+
+static void print_node_to_file(struct addr_node *start, int fd)
+{
+ struct addr_node *t_node;
+
+ t_node = start;
+ fprintf(stderr, "[sys-assert]start print_node_to_file\n");
+ fprintf_fd(fd, "\n%s\n", CRASH_MAPSINFO_TITLE);
+ while (t_node) {
+ if (!strncmp("[anony]", t_node->fpath, strlen("[anony]"))) {
+ t_node = t_node->next;
+ } else {
+ fprintf_fd(fd, "%08x %08x %s %s\n",
+ (unsigned int)t_node->startaddr,
+ (unsigned int)t_node->endaddr,
+ t_node->perm, t_node->fpath);
+ t_node = t_node->next;
+ }
+ }
+ fprintf_fd(fd, "%s\n", CRASH_MAPSINFO_TITLE_E);
+}
+
+static void free_all_nodes(struct addr_node *start)
+{
+ struct addr_node *t_node, *n_node;
+ int fpath_len;
+
+ if (start == NULL)
+ return;
+ t_node = start;
+ n_node = t_node->next;
+ while (t_node) {
+ if (t_node->fpath != NULL) {
+ fpath_len = strlen(t_node->fpath);
+ munmap(t_node->fpath, fpath_len + 1);
+ }
+ munmap(t_node, sizeof(struct addr_node));
+ if (n_node == NULL)
+ break;
+ t_node = n_node;
+ n_node = n_node->next;
+ }
+}
+
+static void print_signal_info(const siginfo_t *info, int fd)
+{
+ int signum = info->si_signo;
+
+ fprintf_fd(fd, "Signal: %d\n", signum);
+ switch (signum) {
+ case SIGINT:
+ fprintf_fd(fd, " (SIGINT)\n");
+ break;
+ case SIGILL:
+ fprintf_fd(fd, " (SIGILL)\n");
+ break;
+ case SIGABRT:
+ fprintf_fd(fd, " (SIGABRT)\n");
+ break;
+ case SIGBUS:
+ fprintf_fd(fd, " (SIGBUS)\n");
+ break;
+ case SIGFPE:
+ fprintf_fd(fd, " (SIGFPE)\n");
+ break;
+ case SIGKILL:
+ fprintf_fd(fd, " (SIGKILL)\n");
+ break;
+ case SIGSEGV:
+ fprintf_fd(fd, " (SIGSEGV)\n");
+ break;
+ case SIGPIPE:
+ fprintf_fd(fd, " (SIGPIPE)\n");
+ break;
+ default:
+ fprintf_fd(fd, "\n");
+ }
+ /* print signal si_code info */
+ fprintf_fd(fd, " si_code: %d\n", info->si_code);
+ if (info->si_code <= 0 || info->si_code >= 0x80) {
+ switch (info->si_code) {
+#ifdef SI_TKILL
+ case SI_TKILL:
+ /* FIXME : print exe name displace with info->si_pid */
+ fprintf_fd(fd,
+ " signal sent by tkill (sent by pid %d, uid %d)\n",
+ info->si_pid, info->si_uid);
+ fprintf_fd(fd, " TIMER: %d\n", SI_TIMER);
+ break;
+#endif
+#ifdef SI_USER
+ case SI_USER:
+ /* FIXME : print exe name displace with info->si_pid */
+ fprintf_fd(fd,
+ " signal sent by kill (sent by pid %d, uid %d)\n",
+ info->si_pid, info->si_uid);
+ break;
+#endif
+#ifdef SI_KERNEL
+ case SI_KERNEL:
+ fprintf_fd(fd, " signal sent by the kernel\n");
+ break;
+#endif
+ }
+
+ } else if (signum == SIGILL) {
+ switch (info->si_code) {
+ case ILL_ILLOPC:
+ fprintf_fd(fd, " illegal opcode\n");
+ break;
+ case ILL_ILLOPN:
+ fprintf_fd(fd, " illegal operand\n");
+ break;
+ case ILL_ILLADR:
+ fprintf_fd(fd, " illegal addressing mode\n");
+ break;
+ case ILL_ILLTRP:
+ fprintf_fd(fd, " illegal trap\n");
+ break;
+ case ILL_PRVOPC:
+ fprintf_fd(fd, " privileged opcode\n");
+ break;
+ case ILL_PRVREG:
+ fprintf_fd(fd, " privileged register\n");
+ break;
+ case ILL_COPROC:
+ fprintf_fd(fd, " coprocessor error\n");
+ break;
+ case ILL_BADSTK:
+ fprintf_fd(fd, " internal stack error\n");
+ break;
+ default:
+ fprintf_fd(fd, " illegal si_code = %d\n", info->si_code);
+ break;
+ }
+ fprintf_fd(fd, " si_addr: %p\n", info->si_addr);
+ } else if (signum == SIGFPE) {
+ switch (info->si_code) {
+ case FPE_INTDIV:
+ fprintf_fd(fd, " integer divide by zero\n");
+ break;
+ case FPE_INTOVF:
+ fprintf_fd(fd, " integer overflow\n");
+ break;
+ case FPE_FLTDIV:
+ fprintf_fd(fd, " floating-point divide by zero\n");
+ break;
+ case FPE_FLTOVF:
+ fprintf_fd(fd, " floating-point overflow\n");
+ break;
+ case FPE_FLTUND:
+ fprintf_fd(fd, " floating-point underflow\n");
+ break;
+ case FPE_FLTRES:
+ fprintf_fd(fd, " floating-point inexact result\n");
+ break;
+ case FPE_FLTINV:
+ fprintf_fd(fd, " invalid floating-point operation\n");
+ break;
+ case FPE_FLTSUB:
+ fprintf_fd(fd, " subscript out of range\n");
+ break;
+ default:
+ fprintf_fd(fd, " illegal si_code: %d\n", info->si_code);
+ break;
+ }
+ } else if (signum == SIGSEGV) {
+ switch (info->si_code) {
+ case SEGV_MAPERR:
+ fprintf_fd(fd, " address not mapped to object\n");
+ break;
+ case SEGV_ACCERR:
+ fprintf_fd(fd,
+ " invalid permissions for mapped object\n");
+ break;
+ default:
+ fprintf_fd(fd, " illegal si_code: %d\n", info->si_code);
+ break;
+ }
+ fprintf_fd(fd, " si_addr = %p\n", info->si_addr);
+ } else if (signum == SIGBUS) {
+ switch (info->si_code) {
+ case BUS_ADRALN:
+ fprintf_fd(fd, " invalid address alignment\n");
+ break;
+ case BUS_ADRERR:
+ fprintf_fd(fd, " nonexistent physical address\n");
+ break;
+ case BUS_OBJERR:
+ fprintf_fd(fd, " object-specific hardware error\n");
+ break;
+ default:
+ fprintf_fd(fd, " illegal si_code: %d\n", info->si_code);
+ break;
+ }
+ fprintf_fd(fd, " si_addr: %p\n", info->si_addr);
+
+ }
+}
+
+
+#define VIP_PATH "/tmp/vip"
+#define PERMANENT_PATH "/tmp/permanent"
+
+static int check_redscreen(int pid)
+{
+ DIR *dp;
+ struct dirent *dirp;
+ char pid_str[10];
+
+ snprintf(pid_str, 10, "%d", pid);
+ if ((dp = opendir(VIP_PATH)) == NULL) {
+ return 0;
+ } else {
+ while ((dirp = readdir(dp)) != NULL) {
+ if (strcmp(dirp->d_name, pid_str) == 0) {
+ fprintf(stderr, "pid=%d is VIP process\n", pid);
+ closedir(dp);
+ return 1;
+ }
+ }
+ }
+ closedir(dp);
+ if ((dp = opendir(PERMANENT_PATH)) == NULL) {
+ return 0;
+ } else {
+ while ((dirp = readdir(dp)) != NULL) {
+ if (strcmp(dirp->d_name, pid_str) == 0) {
+ fprintf(stderr,
+ "pid=%d is Permanent process\n", pid);
+ closedir(dp);
+ return 1;
+ }
+ }
+ }
+ closedir(dp);
+ return 0;
+}
+/*localtime() can not use in signal handler,
+so we need signal safe version of localtime */
+static inline void get_localtime(time_t cur_time, struct tm *ctime)
+{
+ int tday[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ int time_var = cur_time;
+ int i = 0;
+
+ ctime->tm_sec = time_var % 60;
+ time_var /= 60;
+ ctime->tm_min = time_var % 60;
+ time_var /= 60;
+ /* do we need to fix up timze zone ? */
+ ctime->tm_hour = time_var % 24;
+ time_var /= 24;
+ int year = 1970;
+ int leak_year = 0;
+ while (time_var > 365 + (leak_year = (((year % 4) == 0)
+ && ((year % 100) != 0))
+ || ((year % 400) == 0))) {
+ time_var = time_var - 365 - leak_year;
+ year++;
+ }
+ ctime->tm_year = year;
+ leak_year = (((year % 4) == 0) && ((year % 100) != 0))
+ || ((year % 400) == 0);
+ time_var++;
+ while (time_var > tday[i]) {
+ time_var -= tday[i];
+ if (i == 1)
+ time_var -= leak_year;
+ i++;
+ }
+ ctime->tm_mon = ++i;
+ ctime->tm_mday = time_var;
+ fprintf(stderr, "local time %d %d %d %d:%d:%d\n",
+ ctime->tm_year, ctime->tm_mon, ctime->tm_mday,
+ ctime->tm_hour, ctime->tm_min, ctime->tm_sec);
+}
+void sighandler(int signum, siginfo_t *info, void *context)
+{
+ /* for context info */
+ ucontext_t *ucontext = context;
+ void *callstack_addrs[CALLSTACK_SIZE];
+ int cnt_callstack = 0;
+ /* for backtrace_symbols() */
+ char **callstack_strings;
+ struct addr_node *head = NULL;
+ int i;
+ /* file descriptor */
+ int fd_cs; /* for cs file */
+ int fd_maps; /* for maps */
+ int fd_meminfo; /* for meminfo */
+#ifdef STANDALONE
+ int fd_verinfo; /* for version info */
+#endif
+ int fd_cmdline; /* for cmdline */
+ int fd_status; /* for status */
+ int fd_curbs; /* for inotify */
+ pid_t cs_pid;
+ pid_t cs_tid;
+ char cs_timestr[64];
+ char cs_processname[NAME_MAX] = {0,};
+ char cs_exepath[PATH_LEN] = {0,};
+ char cs_filepath[PATH_LEN];
+ /* for get time */
+ time_t cur_time;
+#ifdef STANDALONE
+ struct tm ctime;
+ char timestr[64];
+#endif
+ /* for get info */
+ int thread_use;
+ char *p_exepath = NULL;
+ char tag[64];
+ char infoname[20];
+ char memsize1[24];
+ char linebuf[BUF_SIZE];
+
+ cur_time = time(NULL);
+#ifdef STANDALONE
+ gmtime_r(&cur_time, &ctime);
+ /*localtime_r(&cur_time, &ctime);*/
+ /*get_localtime(cur_time, &ctime);*/
+#endif
+ fprintf(stderr, "[sys_assert]START of sighandler\n");
+ /* get pid */
+ cs_pid = getpid();
+ cs_tid = (long int)syscall(__NR_gettid);
+#ifdef TARGET
+ /* open maps file */
+ if ((fd_maps = open(MAPS_PATH, O_RDONLY)) < 0) {
+ fprintf(stderr, "[sys-assert]can't open %s\n", MAPS_PATH);
+ } else {
+ /* parsing the maps to get code segment address*/
+ head = get_addr_list_from_maps(fd_maps);
+ close(fd_maps);
+ }
+ if (head == NULL) {
+ fprintf(stderr, ">>>>error : cannot get address list from maps\n");
+ } else {
+#ifndef SUPPORT_LIBC_BACKTRACE
+ /* backtrace using fp */
+ long *SP; /* point to the top of stack */
+ long *PC; /* point to the program counter */
+ long *BP = __libc_stack_end;
+ long *FP;
+ long *framep;
+ /* get sp , pc and bp */
+ SP = (long *)ucontext->uc_mcontext.arm_sp;
+ PC = (long *)ucontext->uc_mcontext.arm_pc;
+ FP = (long *)ucontext->uc_mcontext.arm_fp;
+ framep = (long *)FP;
+ callstack_addrs[cnt_callstack++] =
+ (long *)ucontext->uc_mcontext.arm_pc;
+ if (FP != NULL) {
+ for (; framep < BP;) {
+ if (is_valid_addr(framep, head) == false)
+ break;
+
+ if (is_valid_addr((long *)*framep, head) == false)
+ break;
+
+ callstack_addrs[cnt_callstack] = (long *)*framep;
+
+ framep--;
+ framep = (long *)(*framep);
+ cnt_callstack++;
+
+ if (cnt_callstack == CALLSTACK_SIZE)
+ break;
+ if (framep < FP)
+ break;
+ }
+ }
+#else /*SUPPORT_LIBC_BACKTRACE*/
+ cnt_callstack = backtrace(callstack_addrs, CALLSTACK_SIZE);
+ if (cnt_callstack > 2) {
+ cnt_callstack -= 2;
+ } else {
+ callstack_addrs[2] = (long *)ucontext->uc_mcontext.arm_pc;
+ callstack_addrs[3] = (long *)ucontext->uc_mcontext.arm_lr;
+ cnt_callstack = 2;
+ }
+#endif
+ }
+#else /* i386 */
+ layout *ebp = ucontext->uc_mcontext.gregs[REG_EBP];
+ callstack_addrs[cnt_callstack++] =
+ (long *)ucontext->uc_mcontext.gregs[REG_EIP];
+ while (ebp) {
+ callstack_addrs[cnt_callstack++] = ebp->ret;
+ ebp = ebp->ebp;
+ }
+ callstack_strings = backtrace_symbols(callstack_addrs, cnt_callstack);
+#endif
+ /* get exepath */
+ if ((fd_cmdline = open(CMDLINE_PATH, O_RDONLY)) < 0) {
+ fprintf(stderr, "[sys-assert]can't open %s\n", CMDLINE_PATH);
+ return;
+ } else {
+ i = read(fd_cmdline, cs_exepath, sizeof(cs_exepath));
+ close(fd_cmdline);
+ if (i <= 0) {
+ fprintf(stderr, "[sys-assert]can't get cmdline\n");
+ return;
+ } else {
+ cs_exepath[i] = '\0';
+ fprintf(stderr, "[sys-assert]exepath = %s\n", cs_exepath);
+ }
+ }
+ /* get processname */
+ if ((fd_status = open(STATUS_PATH, O_RDONLY)) < 0) {
+ fprintf(stderr, "[sys-assert]can't open %s\n", STATUS_PATH);
+ return;
+ } else {
+ i = read(fd_status, linebuf, sizeof(linebuf));
+ close(fd_status);
+ if (i <= 0) {
+ fprintf(stderr, "[sys-assert]can't get status\n");
+ cs_processname[0] = '\0';
+ } else
+ sscanf(linebuf, "%s %s", tag, cs_processname);
+
+ if (cs_processname[0] == '\0') {
+ p_exepath = remove_path(cs_exepath);
+ if (p_exepath == NULL)
+ return;
+ snprintf(cs_processname, NAME_MAX, "%s", p_exepath);
+ }
+ fprintf(stderr, "[sys-assert]processname = %s\n", cs_processname);
+ }
+ /* added temporary skip when crash-worker is asserted */
+ if (!strcmp(cs_processname, "crash-worker") || !strcmp(cs_processname, "crash-popup"))
+ return;
+ /* thread check */
+ if (cs_pid == cs_tid) {
+ thread_use = false;
+ fprintf(stderr,
+ "[sys_assert]this thread is main thread. pid=%d\n",
+ cs_pid);
+ } else {
+ thread_use = true;
+ fprintf(stderr,
+ "[sys_assert]this process is multi-thread process.\
+ pid=%d, tid=%d\n", cs_pid, cs_tid);
+ }
+ /* make crash info file name */
+#ifdef STANDALONE
+ strftime(cs_timestr, sizeof(cs_timestr), "%Y%m%d%H%M%S", &ctime);
+ if (snprintf(cs_filepath, PATH_LEN,
+ "%s/%s_%s.cs", CRASH_REPORT_PATH, cs_processname, cs_timestr) == 0) {
+ fprintf(stderr,
+ "[sys-assert]can't make crash info file name : %s%s\n",
+ cs_processname, cs_timestr);
+ return;
+ }
+ /* check crash info dump directory, make directory if absent */
+ if (access(CRASH_REPORT_PATH, F_OK) == -1) {
+ if (mkdir(CRASH_REPORT_PATH, DIR_PERMS) < 0) {
+ fprintf(stderr,
+ "[sys-assert]can't make dir : %s errno : %s\n",
+ CRASH_REPORT_PATH, strerror(errno));
+ return;
+ }
+ }
+#else
+ snprintf(cs_timestr, sizeof(cs_timestr), "%lu", cur_time);
+ fprintf(stderr, "[sys-assert]cs timestr %s\n",cs_timestr);
+ if (snprintf(cs_filepath, PATH_LEN,
+ "%s/%d_%s.info", CRASH_INFO_PATH, cs_pid, cs_timestr) == 0) {
+ fprintf(stderr,
+ "[sys-assert]can't make crash info file name : %d%s\n",
+ cs_pid, cs_timestr);
+ return;
+ }
+ /* check crash info dump directory, make directory if absent */
+ if (access(CRASH_INFO_PATH, F_OK) == -1) {
+ if (mkdir(CRASH_INFO_PATH, DIR_PERMS) < 0) {
+ fprintf(stderr,
+ "[sys-assert]can't make dir : %s errno : %s\n",
+ CRASH_INFO_PATH, strerror(errno));
+ return;
+ }
+ }
+#endif
+ /* logging crash information to syslog */
+ syslog(LOG_ERR, "crashed [%s] processname=%s, pid=%d, tid=%d, signal=%d",
+ cs_timestr, cs_processname, cs_pid, cs_tid, info->si_signo);
+ /* complete filepath_cs */
+ if (!strlen(cs_filepath))
+ return;
+ /* create cs file */
+ if ((fd_cs = creat(cs_filepath, FILE_PERMS)) < 0) {
+ fprintf(stderr,
+ "[sys-assert]can't create %s. errno = %s\n",
+ cs_filepath, strerror(errno));
+ return;
+ }
+#ifdef STANDALONE
+ /* print version info */
+ fprintf_fd(fd_cs, "S/W Version Information\n");
+ if ((fd_verinfo = open(VERINFO_PATH, O_RDONLY)) < 0) {
+ fprintf(stderr, "[sys-assert]can't open %s\n", VERINFO_PATH);
+ } else {
+ while (fgets_fd(linebuf, BUF_SIZE, fd_verinfo) != NULL) {
+ if (strncmp("Major=", linebuf, 6) == 0) {
+ fprintf_fd(fd_cs, "%s", linebuf);
+ } else if (strncmp("Minor=", linebuf, 6) == 0) {
+ fprintf_fd(fd_cs, "%s", linebuf);
+ } else if (strncmp("Build=", linebuf, 6) == 0) {
+ fprintf_fd(fd_cs, "%s", linebuf);
+ } else if (strncmp("Date=", linebuf, 5) == 0) {
+ fprintf_fd(fd_cs, "%s", linebuf);
+ } else if (strncmp("Time=", linebuf, 5) == 0) {
+ fprintf_fd(fd_cs, "%s", linebuf);
+ break;
+ }
+ }
+ close(fd_verinfo);
+ }
+ /* print app info */
+ fprintf_fd(fd_cs, "Process Name: %s\n", cs_processname);
+ fprintf_fd(fd_cs, "PID: %d\n", cs_pid);
+ /* print time */
+ /*localtime_r(&cur_time, &ctime);*/
+ strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", &ctime);
+ fprintf_fd(fd_cs, "Date: %s ( UTC )\n", timestr);
+ /* print exe path */
+ fprintf_fd(fd_cs, "Executable File Path: %s\n", cs_exepath);
+ fprintf(stderr, "[sys assert]Exe Path: %s\n", cs_exepath);
+#endif
+ /* print thread info */
+ if (thread_use == true) {
+ fprintf_fd(fd_cs,
+ "This process is multi-thread process\npid=%d tid=%d\n",
+ cs_pid, cs_tid);
+ }
+ /* print signal info */
+ print_signal_info(info, fd_cs);
+ fsync(fd_cs);
+ /* print additional info */
+#ifdef TARGET
+ fprintf_fd(fd_cs, "\n%s\n", CRASH_REGISTERINFO_TITLE);
+ fprintf_fd(fd_cs,
+ "r0 = 0x%08x, r1 = 0x%08x\nr2 = 0x%08x, r3 = 0x%08x\n",
+ ucontext->uc_mcontext.arm_r0,
+ ucontext->uc_mcontext.arm_r1,
+ ucontext->uc_mcontext.arm_r2, ucontext->uc_mcontext.arm_r3);
+ fprintf_fd(fd_cs,
+ "r4 = 0x%08x, r5 = 0x%08x\nr6 = 0x%08x, r7 = 0x%08x\n",
+ ucontext->uc_mcontext.arm_r4,
+ ucontext->uc_mcontext.arm_r5,
+ ucontext->uc_mcontext.arm_r6, ucontext->uc_mcontext.arm_r7);
+ fprintf_fd(fd_cs,
+ "r8 = 0x%08x, r9 = 0x%08x\nr10 = 0x%08x, fp = 0x%08x\n",
+ ucontext->uc_mcontext.arm_r8,
+ ucontext->uc_mcontext.arm_r9,
+ ucontext->uc_mcontext.arm_r10, ucontext->uc_mcontext.arm_fp);
+ fprintf_fd(fd_cs,
+ "ip = 0x%08x, sp = 0x%08x\nlr = 0x%08x, pc = 0x%08x\n",
+ ucontext->uc_mcontext.arm_ip,
+ ucontext->uc_mcontext.arm_sp,
+ ucontext->uc_mcontext.arm_lr, ucontext->uc_mcontext.arm_pc);
+ fprintf_fd(fd_cs, "cpsr = 0x%08x\n", ucontext->uc_mcontext.arm_cpsr);
+#endif
+ /* print meminfo */
+ fprintf_fd(fd_cs, "\n%s\n", CRASH_MEMINFO_TITLE);
+ if ((fd_meminfo = open(MEMINFO_PATH, O_RDONLY)) < 0) {
+ fprintf(stderr, "[sys-assert]can't open %s\n", MEMINFO_PATH);
+ } else {
+ while (fgets_fd(linebuf, BUF_SIZE, fd_meminfo) != NULL) {
+ sscanf(linebuf, "%s %s %*s", infoname, memsize1);
+ if (strcmp("MemTotal:", infoname) == 0) {
+ fprintf_fd(fd_cs, "%s %s KB\n", infoname,
+ memsize1);
+ } else if (strcmp("MemFree:", infoname) == 0) {
+ fprintf_fd(fd_cs, "%s %s KB\n", infoname,
+ memsize1);
+ } else if (strcmp("Buffers:", infoname) == 0) {
+ fprintf_fd(fd_cs, "%s %s KB\n",
+ infoname, memsize1);
+ } else if (strcmp("Cached:", infoname) == 0) {
+ fprintf_fd(fd_cs, "%s %s KB\n",
+ infoname, memsize1);
+ break;
+ }
+ }
+ close(fd_meminfo);
+ }
+#ifdef TARGET
+ if (head == NULL) {
+ fprintf_fd(fd_cs, "Failed to get address list\n");
+ fprintf(stderr, ">>>>error : cannot get address list from maps\n");
+ } else {
+ /* print maps information */
+ print_node_to_file(head, fd_cs);
+ fprintf_fd(fd_cs, "\n%s (PID:%d)\n", CRASH_CALLSTACKINFO_TITLE, cs_pid);
+#ifndef SUPPORT_LIBC_BACKTRACE
+ fprintf_fd(fd_cs, "Call Stack Count: %d\n", cnt_callstack);
+ /* print callstack */
+ if (false ==
+ trace_symbols(callstack_addrs, cnt_callstack, head, fd_cs)) {
+ callstack_strings =
+ backtrace_symbols(callstack_addrs, cnt_callstack);
+ /* print callstack information */
+ for (i = 0; i < cnt_callstack; i++)
+ fprintf_fd(fd_cs, "%2d: %s\n", i, callstack_strings[i]);
+ }
+ if (FP == NULL)
+ fprintf_fd(fd_cs,
+ "there is no callstack because of fp == NULL\n");
+#else /*SUPPORT_LIBC_BACKTRACE*/
+ fprintf_fd(fd_cs, "Call Stack Count: %d\n", cnt_callstack);
+ /* print callstack */
+ if (false ==
+ trace_symbols(&callstack_addrs[2], cnt_callstack, head, fd_cs)) {
+ fprintf(stderr, "[sys-assert] trace_symbols failed\n");
+ }
+#endif
+ fprintf_fd(fd_cs, "%s\n", CRASH_CALLSTACKINFO_TITLE_E);
+ free_all_nodes(head);
+ }
+#else /* i386 */
+ fprintf_fd(fd_cs, "\n%s (PID:%d)\n", CRASH_CALLSTACKINFO_TITLE, cs_pid);
+ fprintf_fd(fd_cs, "Call Stack Count: %d\n", cnt_callstack);
+ /* print callstack information */
+ for (i = 0; i < cnt_callstack; i++)
+ fprintf_fd(fd_cs, "%2d: %s\n", i, callstack_strings[i]);
+ fprintf_fd(fd_cs, "%s\n", CRASH_CALLSTACKINFO_TITLE_E);
+#endif
+ /* cs file sync */
+ fsync(fd_cs);
+ /* clean up */
+ if (close(fd_cs) == -1)
+ fprintf(stderr, "[sys-assert] fd_cs close error!!\n");
+#ifndef STANDALONE
+ /* core dump set */
+ if (prctl(PR_GET_DUMPABLE) == 0) {
+ fprintf(stderr, "[sys-assert]set PR_SET_DUMPABLE to 1\n");
+ prctl(PR_SET_DUMPABLE, 1);
+ }
+ /* NOTIFY CRASH */
+ if ((fd_curbs = open(CRASH_NOTI_PATH, O_RDWR | O_APPEND)) < 0) {
+ fprintf(stderr, "[sys-assert]cannot make %s !\n", CRASH_NOTI_PATH);
+ } else {
+ fprintf_fd(fd_curbs, "S|%s|%s|%d|%s|%d\n",
+ cs_processname, cs_timestr, cs_pid, cs_exepath,
+ strlen(cs_processname) + strlen(cs_exepath));
+ close(fd_curbs);
+ }
+#endif
+ for (i = 0; i < NUM_SIG_TO_HANDLE; i++) {
+ if (sig_to_handle[i] == signum) {
+ sigaction(signum, &g_oldact[i], NULL);
+ fprintf(stderr,
+ "sighandler = %p, g_sig_oldact[i] = %p\n",
+ (void *)sighandler, g_oldact[i].sa_handler);
+ break;
+ }
+ }
+ raise(signum);
+ fprintf(stderr, "[sys_assert]END of sighandler\n");
+}
+__attribute__ ((constructor))
+void init()
+{
+ int i;
+
+ for (i = 0; i < NUM_SIG_TO_HANDLE; i++) {
+ struct sigaction act;
+ act.sa_sigaction = (void *)sighandler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+ act.sa_flags |= SA_RESETHAND;
+ if (sigaction(sig_to_handle[i], &act, &g_oldact[i]) < 0) {
+ perror("[sys-assert]could not set signal handler ");
+ continue;
+ }
+ }
+}