sys-assert: enable sys-assert 52/76252/6 submit/tizen/20160629.015943
authortaeyoung <ty317.kim@samsung.com>
Thu, 23 Jun 2016 07:59:19 +0000 (16:59 +0900)
committertaeyoung <ty317.kim@samsung.com>
Wed, 29 Jun 2016 01:32:00 +0000 (10:32 +0900)
- Now we can choose crash-pipe/crash-stack or sys-assert
  to get callstacks

Change-Id: Ibb166c9206235cd7884aafd31fab008a8003236a
Signed-off-by: taeyoung <ty317.kim@samsung.com>
14 files changed:
CMakeLists.txt
packaging/crash-worker.spec
src/crash-manager/crash-manager.sh.in
src/dump_systemstate/CMakeLists.txt
src/sys-assert/CMakeLists.txt [new file with mode: 0644]
src/sys-assert/arm/backtrace.c [new file with mode: 0644]
src/sys-assert/arm/context.c [new file with mode: 0644]
src/sys-assert/sys-assert.c [new file with mode: 0644]
src/sys-assert/sys-assert.conf.in [new file with mode: 0644]
src/sys-assert/sys-assert.h [new file with mode: 0755]
src/sys-assert/util.c [new file with mode: 0644]
src/sys-assert/util.h [new file with mode: 0644]
src/sys-assert/x86/backtrace.c [new file with mode: 0644]
src/sys-assert/x86/context.c [new file with mode: 0644]

index f273bb0..2f65b81 100644 (file)
@@ -5,7 +5,13 @@ SET(PREFIX ${CMAKE_INSTALL_PREFIX})
 
 # Sub modules
 ADD_SUBDIRECTORY(src/crash-manager)
+
+IF("${SYS_ASSERT}" STREQUAL "on")
+       ADD_SUBDIRECTORY(src/sys-assert)
+ENDIF("${SYS_ASSERT}" STREQUAL "on")
+
 ADD_SUBDIRECTORY(src/crash-pipe)
 ADD_SUBDIRECTORY(src/crash-stack)
+
 ADD_SUBDIRECTORY(src/dump_systemstate)
 
index aacf5bf..dc39f47 100644 (file)
@@ -1,3 +1,5 @@
+%define sys_assert on
+
 Name:      crash-worker
 Summary:    Crash-manager
 Version:    0.2.0
@@ -9,6 +11,9 @@ Source1001:    crash-worker.manifest
 BuildRequires:  pkgconfig(dlog)
 BuildRequires:  pkgconfig(libtzplatform-config)
 BuildRequires:  cmake
+%if "%{?sys_assert}" == "on"
+BuildRequires:  pkgconfig(libunwind)
+%endif
 BuildRequires:  libelf-devel libelf
 BuildRequires:  libebl-devel libebl
 BuildRequires:  libdw-devel libdw
@@ -17,6 +22,7 @@ Requires(post): coreutils
 Requires(post): tar
 Requires(post): gzip
 Requires: libebl
+Requires: libunwind
 
 %description
 crash-manager
@@ -34,13 +40,23 @@ cp %{SOURCE1001} .
 
 export CFLAGS+=" -Werror"
 
+%ifarch %{arm}
+export CFLAGS+=" -DARM"
+%else
+%ifarch %{ix86}
+export CFLAGS+=" -DX86"
+%endif
+%endif
+
+
 %cmake . \
           -DCMAKE_INSTALL_PREFIX=%{_prefix} \
           -DTZ_SYS_BIN=%{TZ_SYS_BIN} \
           -DCRASH_PATH=%{crash_path} \
           -DCRASH_TEMP=%{crash_temp} \
           -DCRASH_PIPE_PATH=%{_libexecdir}/crash-pipe \
-          -DCRASH_STACK_PATH=%{_libexecdir}/crash-stack
+          -DCRASH_STACK_PATH=%{_libexecdir}/crash-stack \
+          -DSYS_ASSERT=%{sys_assert}
 
 make %{?jobs:-j%jobs}
 
@@ -51,6 +67,32 @@ mkdir -p %{buildroot}%{crash_root_path}
 mkdir -p %{buildroot}%{crash_path}
 mkdir -p %{buildroot}%{crash_temp}
 
+
+
+%if "%{?sys_assert}" == "on"
+
+%post
+if [ ! -d /.build ]; then
+       orig="%{_libdir}/libsys-assert.so"
+       pattern=$(echo $orig | sed -e 's|/|\\/|g')
+       ret=$(sed -n "/${pattern}/p"  %{_sysconfdir}/ld.so.preload)
+       if [ -z "$ret" ]; then
+               echo "%{_libdir}/libsys-assert.so" >> %{_sysconfdir}/ld.so.preload
+       fi
+       chmod 644 %{_sysconfdir}/ld.so.preload
+fi
+/sbin/ldconfig
+
+%postun
+orig="%{_libdir}/libsys-assert.so"
+pattern=$(echo $orig | sed -e 's|/|\\/|g')
+sed -i "/${pattern}/D" %{_sysconfdir}/ld.so.preload
+/sbin/ldconfig
+
+%endif
+
+
+
 %files
 %license LICENSE
 %manifest crash-worker.manifest
@@ -60,6 +102,13 @@ mkdir -p %{buildroot}%{crash_temp}
 %dir %{crash_temp}
 %attr(0755,system,system) %{_bindir}/dump_systemstate
 %{_bindir}/crash-manager.sh
+%{_prefix}/lib/sysctl.d/99-crash-manager.conf
+
+%if "%{?sys_assert}" == "on"
+%{_libdir}/libsys-assert.so
+%{_libdir}/tmpfiles.d/sys-assert.conf
+%endif
+
 %{_libexecdir}/crash-pipe
 %{_libexecdir}/crash-stack
-%{_prefix}/lib/sysctl.d/99-crash-manager.conf
+
index fbdc81a..4ab6b58 100644 (file)
@@ -24,11 +24,16 @@ info_path="${pfx}/${name}.info"
 core_path="${pfx}/${name}.coredump"
 log_path="${pfx}/${name}.log"
 tmp_callstack_path="${pfx}/${name}.callstack"
+sysassert_cs_path="/tmp/crash_stack/${cmd}_${pid}.info"
 
 mkdir -p "$CRASH_PATH" "$pfx"
 
 if [ $DEBUG -eq 1 ]
 then
+  if [ "@SYS_ASSERT@" = "on" ]
+  then
+    mv "$sysassert_cs_path" "$pfx/"
+  fi
 #  @CRASH_STACK_PATH@ --pid "$pid" > "$tmp_callstack_path"
   @CRASH_PIPE_PATH@ --save-core "$core_path" --report "$@" > "$info_path"
 #  cat "$tmp_callstack_path" >> "$info_path"
index 8625c10..bd00d95 100755 (executable)
@@ -8,7 +8,7 @@ SET(SRCS
    )
 
 INCLUDE(FindPkgConfig)
-pkg_check_modules(pkgs REQUIRED dlog)
+pkg_check_modules(pkgs REQUIRED dlog libunwind)
 
 FOREACH(flag ${pkgs_CFLAGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
diff --git a/src/sys-assert/CMakeLists.txt b/src/sys-assert/CMakeLists.txt
new file mode 100644 (file)
index 0000000..42f1471
--- /dev/null
@@ -0,0 +1,47 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+SET(LIBNAME sys-assert)
+SET(SRCS
+               sys-assert.c
+               util.c
+)
+
+IF("$ENV{CFLAGS}" MATCHES "-DARM")
+SET(SRCS ${SRCS}
+               arm/context.c
+               arm/backtrace.c
+)
+ELSE("$ENV{CFLAGS}" MATCHES "-DARM")
+SET(SRCS ${SRCS}
+               x86/context.c
+               x86/backtrace.c
+)
+ENDIF("$ENV{CFLAGS}" MATCHES "-DARM")
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(ppkgs REQUIRED libtzplatform-config libunwind)
+
+FOREACH(flag ${ppkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_C_FLAGS_RELEASE "-O2")
+
+FIND_PROGRAM(UNAME NAMES uname)
+EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH")
+IF("${ARCH}" STREQUAL "arm")
+       ADD_DEFINITIONS("-DTARGET")
+       MESSAGE("add -DTARGET")
+ENDIF("${ARCH}" STREQUAL "arm")
+
+ADD_LIBRARY(${LIBNAME} SHARED ${SRCS})
+TARGET_LINK_LIBRARIES(${LIBNAME} ${ppkgs_LDFLAGS} -ldl)
+
+INSTALL(TARGETS ${LIBNAME} LIBRARY DESTINATION ${LIB_INSTALL_DIR})
+
+CONFIGURE_FILE(sys-assert.conf.in sys-assert.conf)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/sys-assert.conf DESTINATION /usr/lib/tmpfiles.d)
diff --git a/src/sys-assert/arm/backtrace.c b/src/sys-assert/arm/backtrace.c
new file mode 100644 (file)
index 0000000..7520bba
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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 <ucontext.h>
+#include <libunwind.h>
+#include <execinfo.h>
+#include "util.h"
+
+int dump_callstack(void **callstack_addrs, int size, void *context, int retry)
+{
+       ucontext_t *ucontext = context;
+       int count;
+
+       if (!callstack_addrs)
+               return 0;
+
+       if (!retry && (context && ((int)ucontext->uc_mcontext.arm_pc != 0)))
+               count = unw_backtrace(callstack_addrs, size);
+       else
+               count = backtrace(callstack_addrs, size);
+
+       if (count > CALLSTACK_BASE) {
+               count -= CALLSTACK_BASE;
+       } else if (context) {
+               callstack_addrs[CALLSTACK_BASE] = (long *)ucontext->uc_mcontext.arm_pc;
+               callstack_addrs[CALLSTACK_BASE] = (long *)ucontext->uc_mcontext.arm_lr;
+               count = 2;
+       } else {
+               count = 0;
+       }
+       return count;
+};
diff --git a/src/sys-assert/arm/context.c b/src/sys-assert/arm/context.c
new file mode 100644 (file)
index 0000000..ec59f9e
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ucontext.h>
+#include "sys-assert.h"
+#include "util.h"
+
+#define CRASH_REGISTERINFO_TITLE "Register Information"
+
+void dump_registers(int fd, void *context)
+{
+       ucontext_t *ucontext = context;
+       /* for context info */
+       if (!context)
+               return;
+
+       fprintf_fd(fd, "\n%s\n", CRASH_REGISTERINFO_TITLE);
+       fprintf_fd(fd,
+               "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,
+               "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,
+               "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,
+               "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, "cpsr = 0x%08x\n",
+               ucontext->uc_mcontext.arm_cpsr);
+};
diff --git a/src/sys-assert/sys-assert.c b/src/sys-assert/sys-assert.c
new file mode 100644 (file)
index 0000000..0fb70de
--- /dev/null
@@ -0,0 +1,827 @@
+/*
+ * SYS-ASSERT
+ * Copyright (c) 2012-2016 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 <string.h>
+#include <stdarg.h>
+#include <errno.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/mman.h>
+#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <sys/sysinfo.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <time.h>
+#include <libunwind.h>
+#include "sys-assert.h"
+#include "util.h"
+
+#define CMDLINE_PATH "/proc/self/cmdline"
+#define EXE_PATH "/proc/self/exe"
+#define MAPS_PATH "/proc/self/maps"
+#define MEMINFO_PATH "/proc/meminfo"
+#define VERINFO_PATH "/etc/info.ini"
+#define STATUS_PATH "/proc/self/status"
+#define TASK_PATH "/proc/self/task"
+
+#define CRASH_INFO_PATH "/tmp/crash_stack"
+#define CRASH_SOCKET "/tmp/crash_socket"
+#define CRASH_SOCKET_PATH_LEN 17
+
+#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_THREADINFO_TITLE "Threads Information"
+
+#define STR_ANONY "[anony]"
+#define STR_ANNOY_LEN 8
+
+#define HEXA 16
+#define PERM_LEN 5
+#define ADDR_LEN 8
+#define INFO_LEN 20
+#define VALUE_LEN 24
+#define TIME_MAX_LEN 64
+#define FILE_LEN 255
+#define BUF_SIZE (BUFSIZ)
+#define CALLSTACK_SIZE 100
+#define FUNC_NAME_MAX_LEN 128
+#define PATH_LEN (FILE_LEN + NAME_MAX)
+
+#define KB(bytes)       ((bytes)/1024)
+
+/* 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[] = {
+       SIGILL, SIGTRAP, SIGABRT, SIGBUS,
+       SIGFPE, SIGSEGV, SIGSTKFLT, SIGXCPU, SIGXFSZ, SIGSYS };
+
+#define NUM_SIG_TO_HANDLE      \
+       ((int)(sizeof(sig_to_handle)/sizeof(sig_to_handle[0])))
+
+struct sigaction g_oldact[NUM_SIG_TO_HANDLE];
+
+extern void dump_registers(int fd, void *context);
+extern int dump_callstack(void **callstack_addrs, int size, void *context, int retry);
+
+/* get function symbol from elf */
+static int trace_symbols(void *const *array, int size, struct addr_node *start, int fd)
+{
+       Dl_info info_funcs;
+       Elf32_Ehdr elf_h;
+       Elf32_Shdr *s_headers;
+       Elf32_Sym *symtab_entry;
+       int i, cnt, file, ret;
+       char *fname;
+       unsigned int addr, start_addr, offset_addr;
+       unsigned int strtab_index = 0;
+       unsigned int symtab_index = 0;
+       int num_st = 0;
+       int found_symtab = 0;
+
+       for (cnt = 0; cnt < size; cnt++) {
+               num_st = 0;
+               /* 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,
+                                       "%2d: (%p) %s\n",
+                                       cnt, array[cnt], dlerror());
+                       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 &&
+                       info_funcs.dli_fname &&
+                       info_funcs.dli_fbase == (void *)BASE_LAUNCHPAD_ADDR &&
+                       (strncmp("/opt/apps/", info_funcs.dli_fname,
+                                        strlen("/opt/apps/")) == 0)) {
+                       info_funcs.dli_fname = get_fpath(array[cnt], start);
+                       offset_addr = addr;
+               } else {
+                       offset_addr = addr - start_addr;
+               }
+
+               /* find symbol from elf file */
+               if (info_funcs.dli_sname == NULL) {
+
+                       /* Both dli_sname and dli_fname is NULL, sys-assert cannot trace any information.
+                          Thus, sys-assert skips to translate such address entry.
+                          However, if a developer wants raw information, we need to fix the code to print raw data */
+                       if(info_funcs.dli_fname == NULL)
+                               continue;
+
+                       file = open(info_funcs.dli_fname, O_RDONLY);
+                       if (file < 0) {
+                               fname = strchr(info_funcs.dli_fname, '/');
+                               if (!fname)
+                                       continue;
+                               file = open(fname, O_RDONLY);
+                               if (file < 0) {
+                                       fprintf_fd(fd,
+                                                       "%2d: (%p) [%s] + %p\n",
+                                                       cnt, array[cnt],
+                                                       info_funcs.dli_fname, offset_addr);
+                                       continue;
+                               }
+                       }
+                       ret = read(file, &elf_h, sizeof(Elf32_Ehdr));
+                       if (ret < sizeof(Elf32_Ehdr) ||
+                                       elf_h.e_shnum <= 0 ||
+                                       SHN_LORESERVE < elf_h.e_shnum) {
+                               fprintf_fd(fd, "%2d: (%p) [%s] + %p\n",
+                                               cnt, array[cnt], info_funcs.dli_fname, offset_addr);
+                               close(file);
+                               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, "%2d: (%p) [%s] + %p\n",
+                                               cnt, array[cnt], info_funcs.dli_fname, offset_addr);
+                               close(file);
+                               continue;
+                       }
+                       ret = lseek(file, elf_h.e_shoff, SEEK_SET);
+                       if (ret < 0 || elf_h.e_shentsize > sizeof(Elf32_Shdr) ||
+                                       elf_h.e_shentsize <= 0) {
+                               close(file);
+                               munmap(s_headers, elf_h.e_shnum * sizeof(Elf32_Shdr));
+                               return -1;
+                       }
+                       for (i = 0; i < elf_h.e_shnum; i++) {
+                               ret = read(file, &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));
+                                       close(file);
+                                       return -1;
+                               }
+                       }
+                       for (i = 0; i < elf_h.e_shnum; i++) {
+                               if (s_headers[i].sh_type == SHT_SYMTAB) {
+                                       symtab_index = i;
+                                       if (s_headers[i].sh_entsize != 0 &&
+                                                       s_headers[i].sh_size != 0) {
+                                               num_st =
+                                                       s_headers[i].sh_size / s_headers[i].sh_entsize;
+                                               found_symtab = 1;
+                                       }
+                                       break;
+                               }
+                       }
+                       if (!found_symtab) {
+                               fprintf(stderr,
+                                               "[sys-assert] can't find symtab\n");
+                               munmap(s_headers, elf_h.e_shnum * sizeof(Elf32_Shdr));
+                               close(file);
+                       } else {
+                               /*.strtab index */
+                               if (symtab_index < elf_h.e_shnum)
+                                       strtab_index = s_headers[symtab_index].sh_link;
+                               if (!strtab_index ||  elf_h.e_shnum <= strtab_index) {
+                                       fprintf_fd(fd, "%2d: (%p) [%s] + %p\n",
+                                               cnt, array[cnt], info_funcs.dli_fname, offset_addr);
+                                       munmap(s_headers, elf_h.e_shnum * sizeof(Elf32_Shdr));
+                                       close(file);
+                                       continue;
+                               }
+                               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));
+                                       close(file);
+                                       return -1;
+                               }
+                               ret = lseek(file, s_headers[symtab_index].sh_offset, SEEK_SET);
+                               if (ret < 0) {
+                                       fprintf_fd(fd, "%2d: (%p) [%s] + %p\n",
+                                               cnt, array[cnt], info_funcs.dli_fname, offset_addr);
+                                       munmap(symtab_entry, sizeof(Elf32_Sym) * num_st);
+                                       munmap(s_headers, elf_h.e_shnum * sizeof(Elf32_Shdr));
+                                       close(file);
+                                       continue;
+                               }
+                               for (i = 0; i < num_st; i++) {
+                                       ret = read(file, &symtab_entry[i], sizeof(Elf32_Sym));
+                                       if (ret < sizeof(Elf32_Sym)) {
+                                               fprintf_fd(fd,
+                                                       "[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) {
+                                                       ret = lseek(file,
+                                                                       s_headers[strtab_index].sh_offset +
+                                                                       symtab_entry[i].st_name,
+                                                                       SEEK_SET);
+                                                       if (ret < 0)
+                                                               break;
+                                                       info_funcs.dli_sname =
+                                                               (void *)mmap(0, FUNC_NAME_MAX_LEN,
+                                                                       PROT_READ | PROT_WRITE,
+                                                                       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+                                                       ret = read(file, (void *)info_funcs.dli_sname,
+                                                                       FUNC_NAME_MAX_LEN);
+                                                       if (ret < 0)
+                                                               break;
+                                                       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(file);
+                       }
+               }
+               /* print symbol name and address. */
+               if (info_funcs.dli_sname != NULL) {
+                       if (array[cnt] >= info_funcs.dli_saddr)
+                               fprintf_fd(fd, "%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, "%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);
+               } else {
+                       fprintf_fd(fd, "%2d: (%p) [%s] + %p\n",
+                                       cnt, array[cnt], info_funcs.dli_fname, offset_addr);
+               }
+       }
+       return 0;
+}
+/* get address list from maps */
+static struct addr_node *get_addr_list_from_maps(int fd)
+{
+       int fpath_len, result;
+       long *saddr;
+       long *eaddr;
+       char perm[PERM_LEN];
+       char path[PATH_LEN];
+       char addr[ADDR_LEN * 2];
+       char linebuf[BUF_SIZE];
+       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) != NULL) {
+               memset(path, 0, PATH_LEN);
+               result = sscanf(linebuf, "%s %s %*s %*s %*s %s ", addr, perm, path);
+               if (result < 0)
+                       continue;
+               perm[PERM_LEN - 1] = 0;
+               /* rwxp */
+#ifdef ARM
+               if ((perm[2] == 'x' && path[0] == '/') ||
+                               (perm[1] == 'w' && path[0] != '/')) {
+#else
+               if (strncmp(perm, "r-xp", strlen("r-xp")) == 0) {
+#endif
+                       /* add addr node to list */
+                       addr[ADDR_LEN] = 0;
+                       saddr = (long *)strtoul(addr, NULL, HEXA);
+                       /* ffff0000-ffff1000 */
+                       eaddr = (long *)strtoul(&addr[ADDR_LEN + 1], NULL, HEXA);
+                       /* 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, PERM_LEN);
+                       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, STR_ANNOY_LEN,
+                                               PROT_READ | PROT_WRITE,
+                                               MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+                               memset(t_node->fpath, 0, STR_ANNOY_LEN);
+                               memcpy(t_node->fpath, STR_ANONY, STR_ANNOY_LEN);
+                       }
+                       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_fd(fd, "\n%s\n", CRASH_MAPSINFO_TITLE);
+       while (t_node) {
+               if (!strncmp(STR_ANONY, t_node->fpath, STR_ANNOY_LEN)) {
+                       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(int signum, const siginfo_t *info, int fd)
+{
+       fprintf_fd(fd, "Signal: %d\n", signum);
+       switch (signum) {
+       case SIGILL:
+               fprintf_fd(fd, "      (SIGILL)\n");
+               break;
+       case SIGTRAP:
+               fprintf_fd(fd, "      (SIGTRAP)\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 SIGSEGV:
+               fprintf_fd(fd, "      (SIGSEGV)\n");
+               break;
+       case SIGTERM:
+               fprintf_fd(fd, "      (SIGTERM)\n");
+               break;
+       case SIGSTKFLT:
+               fprintf_fd(fd, "      (SIGSTKFLT)\n");
+               break;
+       case SIGXCPU:
+               fprintf_fd(fd, "      (SIGXCPU)\n");
+               break;
+       case SIGXFSZ:
+               fprintf_fd(fd, "      (SIGXFSZ)\n");
+               break;
+       case SIGSYS:
+               fprintf_fd(fd, "      (SIGSYS)\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:
+                       fprintf_fd(fd,
+                                       "      signal sent by tkill (sent by pid %d, uid %d)\n",
+                               info->si_pid, info->si_uid);
+                       break;
+#endif
+#ifdef SI_USER
+               case SI_USER:
+                       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);
+       }
+}
+
+void sighandler(int signum, siginfo_t *info, void *context)
+{
+       int idx;
+       int readnum;
+       int threadnum;
+       /* file descriptor */
+       int fd;
+       int fd_cs;              /* for cs file */
+       pid_t pid;
+       pid_t tid;
+       DIR *dir;
+       struct dirent *dentry;
+       char timestr[TIME_MAX_LEN];
+       char processname[NAME_MAX] = {0,};
+       char exepath[PATH_LEN] = {0,};
+       char filepath[PATH_LEN];
+       char crashid[TIME_MAX_LEN] = {0,};
+       /* for get time  */
+       time_t cur_time;
+       /* for get info */
+       char infoname[INFO_LEN];
+       char value[VALUE_LEN];
+       char linebuf[BUF_SIZE];
+       char *p_exepath = NULL;
+       void *callstack_addrs[CALLSTACK_SIZE];
+       int cnt_callstack = 0;
+       /* for backtrace_symbols() */
+       struct addr_node *head = NULL;
+       /* for preventing recursion */
+       static int retry_count = 0;
+       struct sysinfo si;
+
+       if (retry_count > 1) {
+               fprintf(stderr, "[sys-assert] recurcive called\n");
+               return;
+       }
+
+       cur_time = time(NULL);
+       /* get pid */
+       pid = getpid();
+       tid = (long int)syscall(__NR_gettid);
+       /* open maps file */
+       if ((fd = 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);
+               close(fd);
+       }
+       if (retry_count)
+               fprintf(stderr, "retry backtrace in sighandler");
+       cnt_callstack = dump_callstack(callstack_addrs, CALLSTACK_SIZE, context, retry_count);
+       retry_count += 1;
+       /* get exepath */
+       if ((readnum = open_read(CMDLINE_PATH, exepath, sizeof(exepath) - 1)) <= 0) {
+               fprintf(stderr, "[sys-assert]can't read %s\n", CMDLINE_PATH);
+               readnum = snprintf(exepath, sizeof(exepath), "unknown_process");
+       }
+       exepath[readnum] = '\0';
+       /* get processname */
+       if ((p_exepath = remove_path(exepath)) == NULL)
+               return;
+       snprintf(processname, NAME_MAX, "%s", p_exepath);
+       /* added temporary skip  when crash-worker is asserted */
+       if (!strcmp(processname, "crash-worker") ||
+                       !strcmp(processname, "crash-popup"))
+               return;
+       /* make crash info file name */
+       snprintf(timestr, sizeof(timestr), "%.10ld", cur_time);
+       snprintf(crashid, sizeof(crashid), "%s_%d",processname, pid);
+       if (snprintf(filepath, PATH_LEN,
+                               "%s/%s.info", CRASH_INFO_PATH, crashid) == 0) {
+               fprintf(stderr,
+                               "[sys-assert]can't make crash info file name : %s\n",
+                               crashid);
+               return;
+       }
+       /* check crash info dump directory, make directory if absent */
+       if (access(CRASH_INFO_PATH, F_OK) == -1) {
+               fprintf(stderr, "[sys-assert] No directory (%s)", CRASH_INFO_PATH);
+               /*TODO: making directory */
+               return;
+       }
+       /* logging crash information to stderr */
+       fprintf(stderr, "crashed [%s] processname=%s, pid=%d, tid=%d, signal=%d",
+                       timestr, processname, pid, tid, signum);
+       /* complete filepath_cs */
+       if (!strlen(filepath))
+               return;
+       /* create cs file */
+       if ((fd_cs = creat(filepath, FILE_PERMS)) < 0) {
+               fprintf(stderr,
+                               "[sys-assert]can't create %s. errno = %s\n",
+                               filepath, strerror(errno));
+               return;
+       }
+
+       /* print exepath info */
+       fprintf_fd(fd_cs, "Executable File Path: %s\n", exepath);
+
+       /* print signal info */
+       print_signal_info(signum, info, fd_cs);
+       fsync(fd_cs);
+       /* print register info */
+       dump_registers(fd_cs, context);
+
+       /* print meminfo */
+       fprintf_fd(fd_cs, "\n%s\n", CRASH_MEMINFO_TITLE);
+        if (!sysinfo(&si)) {
+                fprintf_fd(fd_cs, "MemTotal: %8ld KB\n", KB(si.totalram));
+                fprintf_fd(fd_cs, "MemFree:  %8ld KB\n", KB(si.freeram));
+                fprintf_fd(fd_cs, "Buffers:  %8ld KB\n", KB(si.bufferram));
+       } else
+               fprintf(stderr, "[sys-assert]can't get sysinfo\n");
+
+       if ((fd = 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) != NULL) {
+                       sscanf(linebuf, "%s %s %*s", infoname, value);
+                       if (strcmp("Cached:", infoname) == 0) {
+                               fprintf_fd(fd_cs, "%s   %8s KB\n", infoname, value);
+                               break;
+                       }
+               }
+               close(fd);
+       }
+
+       threadnum = 0;
+       if ((fd = open(STATUS_PATH, O_RDONLY)) < 0) {
+               fprintf(stderr, "[sys-assert]can't open %s\n", STATUS_PATH);
+       } else {
+               while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) {
+                       sscanf(linebuf, "%s %s %*s", infoname, value);
+                       if (strcmp("VmPeak:", infoname) == 0) {
+                               fprintf_fd(fd_cs, "%s   %8s KB\n", infoname,
+                                               value);
+                       } else if (strcmp("VmSize:", infoname) == 0) {
+                               fprintf_fd(fd_cs, "%s   %8s KB\n", infoname,
+                                               value);
+                       } else if (strcmp("VmLck:", infoname) == 0) {
+                               fprintf_fd(fd_cs, "%s    %8s KB\n", infoname,
+                                               value);
+                       } else if (strcmp("VmPin:", infoname) == 0) {
+                               fprintf_fd(fd_cs, "%s    %8s KB\n", infoname,
+                                               value);
+                       } else if (strcmp("VmHWM:", infoname) == 0) {
+                               fprintf_fd(fd_cs, "%s    %8s KB\n",
+                                               infoname, value);
+                       } else if (strcmp("VmRSS:", infoname) == 0) {
+                               fprintf_fd(fd_cs, "%s    %8s KB\n",
+                                               infoname, value);
+                       } else if (strcmp("VmData:", infoname) == 0) {
+                               fprintf_fd(fd_cs, "%s   %8s KB\n",
+                                               infoname, value);
+                       } else if (strcmp("VmStk:", infoname) == 0) {
+                               fprintf_fd(fd_cs, "%s    %8s KB\n",
+                                               infoname, value);
+                       } else if (strcmp("VmExe:", infoname) == 0) {
+                               fprintf_fd(fd_cs, "%s    %8s KB\n",
+                                               infoname, value);
+                       } else if (strcmp("VmLib:", infoname) == 0) {
+                               fprintf_fd(fd_cs, "%s    %8s KB\n",
+                                               infoname, value);
+                       } else if (strcmp("VmPTE:", infoname) == 0) {
+                               fprintf_fd(fd_cs, "%s    %8s KB\n",
+                                               infoname, value);
+                       } else if (strcmp("VmSwap:", infoname) == 0) {
+                               fprintf_fd(fd_cs, "%s   %8s KB\n",
+                                               infoname, value);
+                       } else if (strcmp("Threads:", infoname) == 0) {
+                               threadnum = atoi(value);
+                               break;
+                       }
+               }
+               close(fd);
+       }
+       /* print thread info */
+       if (1 < threadnum) {
+               fprintf_fd(fd_cs, "\n%s\n", CRASH_THREADINFO_TITLE);
+               fprintf_fd(fd_cs,
+                               "Threads: %d\nPID = %d TID = %d\n",
+                               threadnum, pid, tid);
+               /* print thread */
+               dir = opendir(TASK_PATH);
+               if (!dir) {
+                       fprintf(stderr, "[sys-assert]can't open %s\n", TASK_PATH);
+               } else {
+                       while ((dentry = readdir(dir)) != NULL) {
+                               if( strcmp(dentry->d_name, ".") == 0
+                                               || strcmp(dentry->d_name, "..") == 0)
+                                       continue;
+                               fprintf_fd(fd_cs, "%s ",dentry->d_name);
+                       }
+                       closedir(dir);
+                       fprintf_fd(fd_cs, "\n");
+               }
+       }
+       if (head != NULL) {
+               /* print maps information */
+               print_node_to_file(head, fd_cs);
+               /* print callstack */
+               fprintf_fd(fd_cs, "\n%s (PID:%d)\n", CRASH_CALLSTACKINFO_TITLE, pid);
+               fprintf_fd(fd_cs, "Call Stack Count: %d\n", cnt_callstack);
+               if (trace_symbols(&callstack_addrs[CALLSTACK_BASE],
+                                       cnt_callstack, head, fd_cs) < 0)
+                       fprintf(stderr, "[sys-assert] trace_symbols failed\n");
+               fprintf_fd(fd_cs, "%s\n", CRASH_CALLSTACKINFO_TITLE_E);
+               free_all_nodes(head);
+       }
+       /* cs file sync */
+       fsync(fd_cs);
+       /* clean up */
+       if (close(fd_cs) == -1)
+               fprintf(stderr, "[sys-assert] fd_cs close error!!\n");
+       /* core dump set */
+       if (prctl(PR_GET_DUMPABLE) == 0)
+               prctl(PR_SET_DUMPABLE, 1);
+
+       for (idx = 0; idx < NUM_SIG_TO_HANDLE; idx++) {
+               if (sig_to_handle[idx] == signum) {
+                       sigaction(signum, &g_oldact[idx], NULL);
+                       break;
+               }
+       }
+       raise(signum);
+}
+
+__attribute__ ((constructor))
+void init()
+{
+       int idx;
+
+       for (idx = 0; idx < NUM_SIG_TO_HANDLE; idx++) {
+               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[idx], &act, &g_oldact[idx]) < 0) {
+                       perror("[sys-assert]could not set signal handler ");
+                       continue;
+               }
+       }
+}
diff --git a/src/sys-assert/sys-assert.conf.in b/src/sys-assert/sys-assert.conf.in
new file mode 100644 (file)
index 0000000..29dff1d
--- /dev/null
@@ -0,0 +1,2 @@
+d      /tmp/crash_stack        1777    root    root
+t      /tmp/crash_stack        -       -       -       -       security.SMACK64=*
diff --git a/src/sys-assert/sys-assert.h b/src/sys-assert/sys-assert.h
new file mode 100755 (executable)
index 0000000..7412f3c
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+
+#ifndef _DEBUG_ASSERT_H_
+#define _DEBUG_ASSERT_H_
+
+#include <time.h>
+
+#ifdef ARM
+#define BASE_LAUNCHPAD_ADDR 0x8000
+#else
+#define BASE_LAUNCHPAD_ADDR 0x8048000
+#endif
+#define CALLSTACK_BASE 3
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+       struct addr_node {
+               long *startaddr;
+               long *endaddr;
+               char perm[5];
+               char *fpath;
+               struct addr_node *next;
+       };
+
+#ifdef ARM
+       typedef struct layout {
+               struct layout *fp;
+               void *ret;
+       } layout;
+
+#else
+       typedef struct layout {
+               struct layout *ebp;
+               void *ret;
+       } layout;
+#endif
+
+       extern void *__libc_stack_end;
+
+#ifdef __cplusplus
+}
+#endif
+#endif                         /* _DEBUG_ASSERT_H_ */
diff --git a/src/sys-assert/util.c b/src/sys-assert/util.c
new file mode 100644 (file)
index 0000000..30200ba
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "util.h"
+
+int open_read(const char *path, char *buf, int size)
+{
+       int fd;
+       int ret;
+
+       if (buf == NULL || path == NULL)
+           return -1;
+
+       fd = open(path, O_RDONLY);
+       if (fd < 0)
+           return -1;
+
+       ret = read(fd, buf, size - 1);
+       if (ret <= 0) {
+           close(fd);
+           return -1;
+       } else
+           buf[ret] = '\0';
+
+       close(fd);
+
+       return ret;
+}
+
+char *fgets_fd(char *str, int len, int fd)
+{
+       char ch;
+       register char *cs;
+       int num = 0;
+
+       cs = str;
+       while (--len > 0 && (num = read(fd, &ch, 1) > 0)) {
+               if ((*cs++ = ch) == '\n')
+                       break;
+       }
+       *cs = '\0';
+       return (num == 0 && cs == str) ? NULL : str;
+}
+
+/* WARNING : formatted string buffer is limited to 1024 byte */
+int fprintf_fd(int fd, const char *fmt, ...)
+{
+       int n, ret;
+       char buff[1024];
+       va_list args;
+
+       va_start(args, fmt);
+       n = vsnprintf(buff, 1024 - 1, fmt, args);
+       ret = write(fd, buff, n);
+       if (ret < 0)
+               fprintf(stderr, "write failed\n");
+       va_end(args);
+       return n;
+}
+
+char *remove_path(const char *cmd)
+{
+       char *cp;
+       char *np;
+
+       cp = np = (char *)cmd;
+       while (*cp && *cp != ' ') {
+               if (*cp == '/')
+                       np = cp + 1;
+               cp++;
+       }
+       return np;
+}
+
+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 (n_node) {
+               if (t_node->endaddr <= value) {
+                       t_node = n_node;
+                       n_node = n_node->next;
+               } else if (t_node->startaddr <= value) {
+                       return t_node->fpath;
+               } else
+                       break;
+       }
+       return NULL;
+}
+
+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 (n_node) {
+               if (t_node->endaddr <= value) {
+                       t_node = n_node;
+                       n_node = n_node->next;
+               } else if (t_node->startaddr <= value) {
+                       return t_node->startaddr;
+               } else
+                       break;
+       }
+       return NULL;
+}
diff --git a/src/sys-assert/util.h b/src/sys-assert/util.h
new file mode 100644 (file)
index 0000000..a06077e
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+#include "sys-assert.h"
+
+int open_read(const char *path, char *buf, int size);
+
+char *fgets_fd(char *str, int len, int fd);
+
+/* WARNING : formatted string buffer is limited to 1024 byte */
+int fprintf_fd(int fd, const char *fmt, ...);
+
+char *remove_path(const char *cmd);
+
+char *get_fpath(long *value, struct addr_node *start);
+
+long *get_start_addr(long *value, struct addr_node *start);
diff --git a/src/sys-assert/x86/backtrace.c b/src/sys-assert/x86/backtrace.c
new file mode 100644 (file)
index 0000000..c2ab833
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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 <execinfo.h>
+#include <ucontext.h>
+#include "sys-assert.h"
+#include "util.h"
+
+int dump_callstack(void **callstack_addrs, int size, void *context, int retry)
+{
+       ucontext_t *ucontext = context;
+       int count = CALLSTACK_BASE;
+
+       if (!callstack_addrs)
+               return 0;
+
+       if (context) {
+               layout *ebp = (layout *)ucontext->uc_mcontext.gregs[REG_EBP];
+               callstack_addrs[count++] =
+                       (long *)ucontext->uc_mcontext.gregs[REG_EIP];
+               while (ebp && (count < size)) {
+                       callstack_addrs[count++] = ebp->ret;
+                       ebp = ebp->ebp;
+               }
+       } else {
+               count = backtrace(callstack_addrs, size);
+       }
+
+       if (count > CALLSTACK_BASE) {
+               count -= CALLSTACK_BASE;
+       } else if (context) {
+               callstack_addrs[CALLSTACK_BASE] = (long *)ucontext->uc_mcontext.gregs[REG_EIP];
+               callstack_addrs[CALLSTACK_BASE + 1] = (long *)ucontext->uc_mcontext.gregs[REG_ESP];
+               count = 2;
+       } else {
+               count = 0;
+       }
+       return count;
+};
diff --git a/src/sys-assert/x86/context.c b/src/sys-assert/x86/context.c
new file mode 100644 (file)
index 0000000..20d37bc
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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 <ucontext.h>
+#include "sys-assert.h"
+#include "util.h"
+
+#define CRASH_REGISTERINFO_TITLE "Register Information"
+
+void dump_registers(int fd, void *context)
+{
+       ucontext_t *ucontext = context;
+       /* for context info */
+       if (!context)
+               return;
+
+       fprintf_fd(fd, "\n%s\n", CRASH_REGISTERINFO_TITLE);
+       fprintf_fd(fd,
+               "gs  = 0x%08x, fs  = 0x%08x\nes  = 0x%08x, ds  = 0x%08x\n",
+               ucontext->uc_mcontext.gregs[REG_GS],
+               ucontext->uc_mcontext.gregs[REG_FS],
+               ucontext->uc_mcontext.gregs[REG_ES],
+               ucontext->uc_mcontext.gregs[REG_DS]);
+       fprintf_fd(fd,
+               "edi = 0x%08x, esi = 0x%08x\nebp = 0x%08x, esp = 0x%08x\n",
+               ucontext->uc_mcontext.gregs[REG_EDI],
+               ucontext->uc_mcontext.gregs[REG_ESI],
+               ucontext->uc_mcontext.gregs[REG_EBP],
+               ucontext->uc_mcontext.gregs[REG_ESP]);
+       fprintf_fd(fd,
+               "eax = 0x%08x, ebx = 0x%08x\necx = 0x%08x, edx = 0x%08x\n",
+               ucontext->uc_mcontext.gregs[REG_EAX],
+               ucontext->uc_mcontext.gregs[REG_EBX],
+               ucontext->uc_mcontext.gregs[REG_ECX],
+               ucontext->uc_mcontext.gregs[REG_EDX]);
+       fprintf_fd(fd,
+               "eip = 0x%08x\n",
+               ucontext->uc_mcontext.gregs[REG_EIP]);
+};