crash-stack: use libunwind for i686 and x86_64 52/105152/2
authorRafal Pietruch <r.pietruch@samsung.com>
Thu, 15 Dec 2016 15:28:17 +0000 (16:28 +0100)
committerŁukasz Stelmach <l.stelmach@samsung.com>
Tue, 20 Dec 2016 12:39:10 +0000 (13:39 +0100)
Change-Id: I0022cc3ac772ba26ed67f7d64d45c3ab4e22db88

src/crash-stack/CMakeLists.txt
src/crash-stack/crash-stack-libelf-helpers.c
src/crash-stack/crash-stack-libelf.c [deleted file]
src/crash-stack/crash-stack-libunw.c
src/crash-stack/crash-stack-x86.c

index ccf845e..499c9dc 100644 (file)
@@ -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})
index ab95350..8239a05 100644 (file)
@@ -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 (file)
index c341c96..0000000
+++ /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
-}
-
index 23e3df3..f013e63 100644 (file)
@@ -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;
                }
index b63f279..a72a198 100644 (file)
@@ -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)