summaryrefslogtreecommitdiff
path: root/src/crash-stack
diff options
context:
space:
mode:
authorKarol Lewandowski <k.lewandowsk@samsung.com>2016-12-20 09:33:58 -0800
committerGerrit Code Review <gerrit@review.vlan103.tizen.org>2016-12-20 09:33:58 -0800
commite446d126daf8c708373ac89a36854e73af44888c (patch)
treeb5e7b882544db846dab504cc6beb52de2c7e7b8e /src/crash-stack
parente4769d50f923dfc702c8396b63346d8b273ccc08 (diff)
parentc954427bb005de2308e92d8f70284b1301fe35c3 (diff)
downloadcrash-worker-e446d126daf8c708373ac89a36854e73af44888c.tar.gz
crash-worker-e446d126daf8c708373ac89a36854e73af44888c.tar.bz2
crash-worker-e446d126daf8c708373ac89a36854e73af44888c.zip
Merge "crash-stack: use libunwind for i686 and x86_64" into tizen_3.0
Diffstat (limited to 'src/crash-stack')
-rw-r--r--src/crash-stack/CMakeLists.txt28
-rw-r--r--src/crash-stack/crash-stack-libelf-helpers.c46
-rw-r--r--src/crash-stack/crash-stack-libelf.c180
-rw-r--r--src/crash-stack/crash-stack-libunw.c9
-rw-r--r--src/crash-stack/crash-stack-x86.c24
5 files changed, 30 insertions, 257 deletions
diff --git a/src/crash-stack/CMakeLists.txt b/src/crash-stack/CMakeLists.txt
index ccf845e..499c9dc 100644
--- a/src/crash-stack/CMakeLists.txt
+++ b/src/crash-stack/CMakeLists.txt
@@ -4,22 +4,24 @@ option(WITH_CORE_DUMP "builds with support for core dump files (with GPL2 licens
set(CRASH_STACK_BIN "crash-stack")
# Common source code files
-set(CRASH_STACK_SRCS crash-stack.c crash-stack-libelf-helpers.c)
+set(CRASH_STACK_SRCS crash-stack.c)
+
# Add architecture dependent source files
-if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv7l")
- set(CRASH_STACK_SRCS ${CRASH_STACK_SRCS} crash-stack-libunw.c)
- set(CRASH_STACK_SRCS ${CRASH_STACK_SRCS} crash-stack-arm.c)
+if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
+ set(CRASH_STACK_SRCS ${CRASH_STACK_SRCS} crash-stack-aarch64.c)
+ set(CRASH_STACK_SRCS ${CRASH_STACK_SRCS} crash-stack-libelf-helpers.c)
+
else()
- if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
- set(CRASH_STACK_SRCS ${CRASH_STACK_SRCS} crash-stack-aarch64.c)
- elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
- set(CRASH_STACK_SRCS ${CRASH_STACK_SRCS} crash-stack-libelf.c)
- set(CRASH_STACK_SRCS ${CRASH_STACK_SRCS} crash-stack-x86.c)
- elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i686")
- set(CRASH_STACK_SRCS ${CRASH_STACK_SRCS} crash-stack-libelf.c)
+ set(CRASH_STACK_SRCS ${CRASH_STACK_SRCS} crash-stack-libunw.c)
+
+ if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv7l")
+ set(CRASH_STACK_SRCS ${CRASH_STACK_SRCS} crash-stack-arm.c)
+
+ elseif ((${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
+ OR (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i686"))
set(CRASH_STACK_SRCS ${CRASH_STACK_SRCS} crash-stack-x86.c)
+
else()
- set(CRASH_STACK_SRCS ${CRASH_STACK_SRCS} crash-stack-libelf.c)
set(CRASH_STACK_SRCS ${CRASH_STACK_SRCS} crash-stack-stub.c)
endif()
endif()
@@ -28,7 +30,7 @@ endif()
add_executable(${CRASH_STACK_BIN} ${CRASH_STACK_SRCS})
# Set architecture dependent options for the binary - it must be already added
-if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv7l")
+if (NOT (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64"))
include(FindPkgConfig)
pkg_check_modules(LIBUNWIND_PTRACE REQUIRED libunwind-ptrace)
set_property(TARGET ${CRASH_STACK_BIN} APPEND_STRING PROPERTY COMPILE_FLAGS ${LIBUNWIND_PTRACE_CFLAGS_OTHER})
diff --git a/src/crash-stack/crash-stack-libelf-helpers.c b/src/crash-stack/crash-stack-libelf-helpers.c
index ab95350..8239a05 100644
--- a/src/crash-stack/crash-stack-libelf-helpers.c
+++ b/src/crash-stack/crash-stack-libelf-helpers.c
@@ -92,49 +92,3 @@ bool _crash_stack_libelf_read_value(Dwfl *dwfl, Elf *core, pid_t pid,
return false;
}
-
-Dwarf_Addr _crash_stack_libelf_get_prologue_pc(Dwfl *dwfl, Dwarf_Addr current_pc, Mappings *mappings)
-{
- Dwarf_Addr result = 0;
- Dwfl_Module *module = dwfl_addrmodule(dwfl, current_pc);
- if (module) {
- GElf_Sym sym;
- dwfl_module_addrsym(module, current_pc, &sym, NULL);
- result = sym.st_value;
- }
- if (0 == result) {
- int i;
- for (i=0; i < mappings->elems; i++) {
- if (mappings->tab[i].m_start <= current_pc && current_pc < mappings->tab[i].m_end) {
- /* go through symbols to find the nearest */
- Elf_Scn *scn = NULL;
- Elf *elf = mappings->tab[i].m_elf;
- while ((scn = elf_nextscn(elf, scn)) != NULL) {
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr(scn, &shdr_mem);
- if (shdr != NULL && (shdr->sh_type == SHT_SYMTAB || shdr->sh_type == SHT_DYNSYM)) {
- Elf_Data *sdata = elf_getdata(scn, NULL);
- unsigned int nsyms = sdata->d_size / (gelf_getclass(elf) == ELFCLASS32 ?
- sizeof(Elf32_Sym) :
- sizeof(Elf64_Sym));
- unsigned int cnt;
- uintptr_t address_offset = current_pc;
- if (shdr->sh_type == SHT_DYNSYM)
- address_offset -= mappings->tab[i].m_start;
- for (cnt = 0; cnt < nsyms; ++cnt) {
- GElf_Sym sym_mem;
- Elf32_Word xndx;
- GElf_Sym *sym = gelf_getsymshndx(sdata, NULL, cnt, &sym_mem, &xndx);
- if (sym != NULL && sym->st_shndx != SHN_UNDEF) {
- if (sym->st_value <= address_offset && address_offset < sym->st_value + sym->st_size) {
- return sym->st_value;
- }
- }
- }
- }
- }
- }
- }
- }
- return result;
-}
diff --git a/src/crash-stack/crash-stack-libelf.c b/src/crash-stack/crash-stack-libelf.c
deleted file mode 100644
index c341c96..0000000
--- a/src/crash-stack/crash-stack-libelf.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- *
- * Copyright (c) 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.
- *
- * Author: Adrian Szyndela <adrian.s@samsung.com>
- */
-/**
- * @file crash-stack-libelf.c
- * @brief unwinding call stacks, functions specific for archs that use only libelf
- */
-#include "crash-stack.h"
-#include <elfutils/libdwfl.h>
-#include <elfutils/version.h>
-#include <string.h>
-
-/**
- * @brief Convenience type for registers of different sizes
- */
-typedef union {
- uint16_t reg16; ///< 16-bit register
- uint32_t reg32; ///< 32-bit register
- uint64_t reg64; ///< 64-bit register
-} Register;
-
-static Register g_pc; ///< storage for program counter value
-static Register g_sp; ///< storage for stack pointer value
-
-#if _ELFUTILS_PREREQ(0,158)
-/**
- * @brief Callback for modern elfutils; called on each found frame.
- *
- * @param state state of the calls tack traversal
- * @param arg user data - pointer to callstack database
- */
-static int __frame_callback(Dwfl_Frame *state, void *arg)
-{
- Callstack *callstack = (Callstack*)arg;
- Dwarf_Addr address;
- dwfl_frame_pc(state, &address, NULL);
- callstack->proc[callstack->elems++].addr = address;
- return callstack->elems < MAX_CALLSTACK_LEN ? DWARF_CB_OK : DWARF_CB_ABORT;
-}
-
-/**
- * @brief Callback for modern elfutils; called on each found thread.
- *
- * @param thread thread handle
- * @param thread_arg user data - pointer to callstack database
- */
-static int __thread_callback(Dwfl_Thread *thread, void *thread_arg)
-{
- dwfl_thread_getframes(thread, __frame_callback, thread_arg);
- return DWARF_CB_ABORT;
-}
-#endif
-
-/**
- * @brief common names for program counter/instruction pointer
- */
-static const char *pc_names[] = {
- "pc", "rip", "eip", "ip"
-};
-
-/**
- * @brief common names for stack pointer
- */
-static const char *sp_names[] = {
- "sp", "rsp", "esp"
-};
-
-/**
- * @brief Helper functions that checks if a name is present in array of names
- *
- * @param name name to look for
- * @param names array of names
- * @param elems number of elements in names
- * @returns true if name is found in names, false otherwise
- */
-static bool __is_in(const char *name, const char **names, int elems)
-{
- int nit;
- for (nit = 0; nit < elems; ++nit) {
- if (strcmp(name, names[nit]) == 0)
- return true;
- }
- return false;
-}
-
-/**
- * @brief Helper macro for looking for name in array of names
- */
-#define IS_IN(name,names) __is_in((name), (names), sizeof(names)/sizeof(names[0]))
-
-void *_get_place_for_register_value(const char *regname, int regnum)
-{
- if (IS_IN(regname, pc_names)) return &g_pc;
- else if (IS_IN(regname, sp_names)) return &g_sp;
-
- return 0;
-}
-
-/**
- * @brief Tries to heuristically gather call stack information.
- *
- * @remarks This function walks through the stack of the given process, and checks
- * if found addresses are addresses belonging to functions. If so, it treats
- * such address as an element of the call stack.
- * While it gathers some useful information, it gathers also "false positives".
- * @remarks It should be used as a last resort - when no other method is available.
- *
- * @param dwfl dwfl handle
- * @param core core file handle, NULL if live process is analyzed
- * @param pid PID of the analyzed process, 0 if core dump file is analyzed
- * @param mappings module mappings database
- * @param callstack call stack database
- */
-static void _explore_stack_in_search_of_functions(Dwfl *dwfl, Elf *core, pid_t pid,
- Mappings *mappings, Callstack *callstack)
-{
- Dwarf_Addr stack_pointer = sizeof(uintptr_t) == 4 ? g_sp.reg32 : g_sp.reg64;
- Dwarf_Addr stack_max_lookup = stack_pointer + 8*1024*1024;
- bool data_remaining = true;
- do {
- uintptr_t value;
- data_remaining = _crash_stack_libelf_read_value(dwfl, core, pid, stack_pointer,
- &value, sizeof(value), mappings);
- if (data_remaining) {
- Dwarf_Addr bias;
- /* check presence of address in text sections */
- Dwfl_Module *module = dwfl_addrmodule(dwfl, value);
- if (module != NULL) {
- Dwarf_Addr elfval = value;
- GElf_Sym sym;
- GElf_Word shndxp = -1;
- dwfl_module_addrsym(module, value, &sym, &shndxp);
- Elf_Scn *scn = dwfl_module_address_section(module, &elfval, &bias);
- if (scn != 0 || shndxp != -1) {
- callstack->proc[callstack->elems++].addr = value;
- if (callstack->elems >= MAX_CALLSTACK_LEN)
- return;
- }
- else {
- /* check also inside [pie] and [exe] */
- int i;
- for (i = 0; i < mappings->elems; i++) {
- if (mappings->tab[i].m_start <= elfval && elfval < mappings->tab[i].m_end) {
- callstack->proc[callstack->elems++].addr = value;
- break;
- }
- }
- }
- }
- }
- stack_pointer += sizeof(uintptr_t);
- } while (data_remaining && stack_pointer < stack_max_lookup);
-}
-
-void _create_crash_stack(Dwfl *dwfl, Elf *core, pid_t pid, Mappings *mappings, Callstack *callstack)
-{
- callstack->elems = 0;
-#if _ELFUTILS_PREREQ(0,158)
- dwfl_getthreads(dwfl, __thread_callback, callstack);
-#else
- callstack->proc[callstack->elems++].addr = sizeof(uintptr_t) == 4 ? g_pc.reg32 : g_pc.reg64;
- _explore_stack_in_search_of_functions(dwfl, core, pid, mappings, callstack);
-#endif
-}
-
diff --git a/src/crash-stack/crash-stack-libunw.c b/src/crash-stack/crash-stack-libunw.c
index 23e3df3..f013e63 100644
--- a/src/crash-stack/crash-stack-libunw.c
+++ b/src/crash-stack/crash-stack-libunw.c
@@ -33,6 +33,7 @@ void _create_crash_stack(Dwfl *dwfl, Elf *core, pid_t pid, Mappings *mappings, C
unw_addr_space_t as = 0;
void *ui = 0;
do {
+ //init before return
callstack->elems = 0;
as = unw_create_addr_space(&_UPT_accessors, 0);
@@ -48,11 +49,8 @@ void _create_crash_stack(Dwfl *dwfl, Elf *core, pid_t pid, Mappings *mappings, C
break;
char proc_name[MAXPROCNAMELEN];
- int n;
- // MaxDeep as proposed in libunwind tests/test-ptrace.c file
- // guard against bad unwind info in old libraries
- static const int MaxDeep = 64;
- for (n = 0; n < MaxDeep; ++n) {
+ for (; callstack->elems < sizeof(callstack->proc)/sizeof(callstack->proc[0]);
+ ++callstack->elems) {
unw_word_t ip;
if (unw_get_reg(&cursor, UNW_REG_IP, &ip) < 0)
@@ -66,7 +64,6 @@ void _create_crash_stack(Dwfl *dwfl, Elf *core, pid_t pid, Mappings *mappings, C
callstack->proc[callstack->elems].name = strdup(proc_name);
callstack->proc[callstack->elems].offset = off;
- ++callstack->elems;
if (unw_step(&cursor) <= 0)
break;
}
diff --git a/src/crash-stack/crash-stack-x86.c b/src/crash-stack/crash-stack-x86.c
index b63f279..a72a198 100644
--- a/src/crash-stack/crash-stack-x86.c
+++ b/src/crash-stack/crash-stack-x86.c
@@ -33,20 +33,20 @@ void *_crash_stack_get_memory_for_ptrace_registers(size_t *size)
return &g_registers;
}
-void _crash_stack_set_ptrace_registers(void *regbuf)
+void *_get_place_for_register_value(const char *regname, int regnum)
{
- void *rsp = _get_place_for_register_value("rsp", 0);
- void *rip = _get_place_for_register_value("rip", 0);
-
- struct user_regs_struct *regs = regbuf;
+ /* Function is not used for x86 anymore, make it dummy
+ * It is still called by generic __get_registers_core function
+ * The return value is checked for NULL in __get_registers_core.
+ */
+ return NULL;
+}
-#if defined(__x86_64__)
- memcpy(rsp, &regs->rsp, sizeof(regs->rsp));
- memcpy(rip, &regs->rip, sizeof(regs->rip));
-#else
- memcpy(rsp, &regs->esp, sizeof(regs->esp));
- memcpy(rip, &regs->eip, sizeof(regs->eip));
-#endif
+void _crash_stack_set_ptrace_registers(void *regbuf)
+{
+ /* Make it dummy as it not used for x86 anymore
+ * However it is still called by generic __get_registers_ptrace functions
+ */
}
void _crash_stack_print_regs(FILE* outputfile)