crash-stack: remove the core dump handling remains 60/108060/3
authorAdrian Szyndela <adrian.s@samsung.com>
Mon, 2 Jan 2017 14:03:58 +0000 (15:03 +0100)
committerŁukasz Stelmach <l.stelmach@samsung.com>
Thu, 2 Feb 2017 12:36:24 +0000 (13:36 +0100)
Hopefully, there is no more rotting flesh.

Change-Id: I59003e8a38dd2817f78d23319848273615a0a5be

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

index 807d898..77ff0ce 100644 (file)
@@ -1,6 +1,5 @@
 cmake_minimum_required(VERSION 2.8.11)
 
-option(WITH_CORE_DUMP "builds with support for core dump files (with GPL2 license)")
 set(CRASH_STACK_BIN "crash-stack")
 
 # Common source code files
@@ -28,12 +27,6 @@ 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})
 
-# Set compilation options for core dump support
-if (${WITH_CORE_DUMP} STREQUAL "ON")
-  set_property(TARGET ${CRASH_STACK_BIN} APPEND_STRING PROPERTY COMPILE_FLAGS " -DWITH_CORE_DUMP")
-  find_library(EBL_LIBRARY NAMES ebl)
-endif()
-
 # Linking
 target_link_libraries(${CRASH_STACK_BIN} ${LIBUNWIND_PTRACE_LIBRARIES} ${EBL_LIBRARY} dw elf dl stdc++)
 # Installing
diff --git a/src/crash-stack/crash-stack-libelf-helpers.c b/src/crash-stack/crash-stack-libelf-helpers.c
deleted file mode 100644 (file)
index 8239a05..0000000
+++ /dev/null
@@ -1,94 +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-helpers.c
- * @brief unwinding call stacks, functions for accessing libelf for other
- * purposes than unwinding
- */
-#include "crash-stack.h"
-#include <string.h>
-#include <sys/ptrace.h>
-#include <errno.h>
-
-bool _crash_stack_libelf_read_value(Dwfl *dwfl, Elf *core, pid_t pid,
-               Dwarf_Addr a, void *v, size_t size,
-               Mappings *mappings)
-{
-       Dwfl_Module *module = 0;
-       Elf_Data *data = NULL;
-
-       int segment = dwfl_addrsegment(dwfl, a, &module);
-
-       if (module != NULL) {
-               Dwarf_Addr start;
-               dwfl_module_info(module, NULL, &start, NULL, NULL, NULL, NULL, NULL);
-
-               GElf_Addr bias;
-               Elf *elf = dwfl_module_getelf(module, &bias);
-
-               data = elf_getdata_rawchunk(elf, a-start, size, ELF_T_BYTE);
-       }
-       if (NULL == data && segment != -1) {
-               // get data from segment
-               GElf_Phdr mem;
-               GElf_Phdr *phdr = gelf_getphdr(core, segment, &mem);
-               Dwarf_Addr offset_in_segment = a - phdr->p_vaddr;
-               if (offset_in_segment < phdr->p_filesz) {
-                       Dwarf_Addr offset_in_file = phdr->p_offset + offset_in_segment;
-
-                       data = elf_getdata_rawchunk(core, offset_in_file, size, ELF_T_BYTE);
-               }
-       }
-
-       if (NULL == data && module != NULL) {
-               const char *name = dwfl_module_info(module, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
-               if (name != NULL && name[0] == '[') {
-                       int i;
-                       // get module from mappings
-                       for (i = 0; i < mappings->elems; i++) {
-                               if (mappings->tab[i].m_start <= a && a < mappings->tab[i].m_end) {
-                                       // compute offset relative to the start of the mapping
-                                       long offset = a - mappings->tab[i].m_start;
-                                       // read from the file, but also account file offset
-                                       data = elf_getdata_rawchunk(mappings->tab[i].m_elf,
-                                                       offset + mappings->tab[i].m_offset, size, ELF_T_BYTE);
-                                       break;
-                               }
-                       }
-               }
-       }
-
-       if (data != NULL) {
-               memcpy(v, data->d_buf, size);
-               return true;
-       }
-
-       /* Still no data, but we have a process - read memory with ptrace */
-       /* FIXME need to know if we are still in the mapped area */
-       /* Bigger issue is that dwfl does not have modules */
-       if (pid > 1) {
-               long val = ptrace(PTRACE_PEEKDATA, pid, a, NULL);
-               if (-1 == val && errno)
-                       return false;
-               memcpy(v, &val, size);
-               return true;
-       }
-
-       return false;
-}
index b9b9c35..544a3e4 100644 (file)
@@ -25,7 +25,7 @@
 
 #define MAXPROCNAMELEN 512
 
-void _create_crash_stack(Dwfl *dwfl, Elf *core, pid_t pid, Mappings *mappings, Callstack *callstack)
+void _create_crash_stack(Dwfl *dwfl, pid_t pid, Callstack *callstack)
 {
        // reimplemented based on libunwind tests/test-ptrace.c file
        unw_addr_space_t as = 0;
index 142b247..00d19b6 100644 (file)
@@ -25,7 +25,7 @@
  *
  * Crash-stack is a single purpose program. Its duty is to show call stack
  * of a crashed program. Crash-stack must be called with proper arguments:
- * either core dump file name or PID of a crashed program.
+ * PID of a crashed program.
  */
 #include "crash-stack.h"
 #include <dirent.h>
@@ -123,116 +123,10 @@ static int __module_callback(Dwfl_Module *module, void **userdata,
                const char *name, Dwarf_Addr address,
                void *arg)
 {
-       if (name != NULL && name[0] == '[') {
-               /* libdwfl couldn't get the module file - we will get it later from notes */
-               Mappings *mappings = arg;
-               if (mappings->elems < MAX_MAPPINGS_NUM) {
-                       size_t elems = mappings->elems;
-                       mappings->tab[elems].m_start = address;
-                       mappings->tab[elems].m_end = 0;
-                       mappings->tab[elems].m_offset = 0;
-                       mappings->tab[elems].m_name = NULL;
-                       mappings->tab[elems].m_fd = -1;
-                       mappings->tab[elems].m_elf = 0;
-                       mappings->elems++;
-               }
-       }
        return DWARF_CB_OK;
 }
 
-/**
- * @brief Reads a value of specified size from core dump file.
- *
- * @param core ELF handler for the core dump file
- * @param from the source address in the ELF file
- * @param size size of the value in bits
- * @param to the address of allocated memory, where the value will be copied
- */
-static void __get_value(Elf *core, const void *from, size_t size, void *to)
-{
-       Elf_Type type = ELF_T_BYTE;
-       switch (size) {
-       case 8: type = ELF_T_BYTE; break;
-       case 16: type = ELF_T_HALF; break;
-       case 32: type = ELF_T_WORD; break;
-       case 64: type = ELF_T_XWORD; break;
-       default:
-                fprintf(errfile, "__get_value for strange size: %llu\n", (unsigned long long)size);
-                break;
-       }
-       Elf_Data out = {
-               .d_buf = to,
-               .d_type = type,
-               .d_version = EV_CURRENT,
-               .d_size = size/8,
-               .d_off = 0,
-               .d_align = 0
-       };
-       Elf_Data in = {
-               .d_buf = (void*)(from),
-               .d_type = out.d_type,
-               .d_version = out.d_version,
-               .d_size = out.d_size,
-               .d_off = 0,
-               .d_align = 0
-       };
-       Elf_Data *data;
-       if (gelf_getclass(core) == ELFCLASS32)
-               data = elf32_xlatetom(&out, &in, elf_getident(core, NULL)[EI_DATA]);
-       else
-               data = elf64_xlatetom(&out, &in, elf_getident(core, NULL)[EI_DATA]);
-       if (data == NULL)
-               fprintf(errfile, "failed to get value from core file\n");
-}
-
-/**
- * @brief gets number of values, page size, address size, values and names from ELF notes
- *
- * @remarks This is very specific for organization of notes part in ELF files
- *
- * @param elf ELF handler - may be core file
- * @param desc address of ELF notes descriptor
- * @param[out] values_cnt a place for number of values
- * @param[out] page_size a place for page size
- * @param[out] addr_size a place for address size
- * @param[out] values a place for address of values
- * @param[out] filenames a place for address of filenames
- */
-static void __parse_note_file(Elf *elf, const char *desc, uint64_t *values_cnt, uint64_t *page_size,
-               size_t *addr_size, const char **values, const char **filenames)
-{
-       *addr_size = gelf_fsize(elf, ELF_T_ADDR, 1, EV_CURRENT);
-       __get_value(elf, desc, *addr_size*8, values_cnt);
-       __get_value(elf, desc + *addr_size, *addr_size*8, page_size);
-       /* First: triplets of <mapping-start> <mapping-end> <offset-in-pages>
-        *     count = values_cnt
-        * Then the names of files.
-        */
-       *values = desc + 2 * *addr_size;
-       *filenames = *values + 3 * *addr_size * *values_cnt;
-}
-
-/**
- * @brief Simple accessor for mapping items in ELF files
- *
- * @remarks This is very specific for organization of notes part in ELF files
- *
- * @param elf ELF handler - may be core file
- * @param addr_size size of addresses in this ELF
- * @param item address of mapping item to get data from
- * @param[out] mapping_start value of the start of the mapping
- * @param[out] mapping_end value of the end of the mapping
- * @param[out] offset_in_pages number of pages of offset in the file
- */
-static void __get_mapping_item(Elf *elf, size_t addr_size, const void *item,
-               uint64_t *mapping_start, uint64_t *mapping_end, uint64_t *offset_in_pages)
-{
-       __get_value(elf, item, addr_size*8, mapping_start);
-       __get_value(elf, item + addr_size, addr_size*8, mapping_end);
-       __get_value(elf, item + 2 * addr_size, addr_size*8, offset_in_pages);
-}
-
-void __find_symbol_in_elf(ProcInfo *proc_info, Dwarf_Addr mapping_start)
+static void __find_symbol_in_elf(ProcInfo *proc_info, Dwarf_Addr mapping_start)
 {
        Elf *elf;
        int fd;
@@ -506,56 +400,6 @@ static void __resolve_symbols_from_dwfl(ProcInfo *proc_info, Dwfl *dwfl)
 }
 
 /**
- * @brief Resolves procedure and module names using elfutils
- *
- * @remarks This function is used in case that symbol name is not available by libelf,
- *                     e.g. when old libelf version does not take into account some modules.
- *
- * @param proc_info gathered call stack element
- * @param core ELF handler for the core dump file, NULL if live process analyzed
- * @param notes notes handler, NULL if live process analyzed
- */
-static void __resolve_symbols_from_elf(ProcInfo *proc_info, Elf *core, Elf_Data *notes)
-{
-       GElf_Nhdr nhdr;
-       size_t pos = 0;
-       size_t new_pos = 0;
-       size_t name_pos;
-       size_t desc_pos;
-
-       while ((new_pos = gelf_getnote(notes, pos, &nhdr, &name_pos, &desc_pos)) > 0) {
-               if (nhdr.n_type == NT_FILE) {
-                       uint64_t values_cnt = 0, page_size = 0;
-                       const char *values;
-                       const char *filenames;
-                       size_t addr_size = 0;
-
-                       __parse_note_file(core, notes->d_buf + desc_pos, &values_cnt,
-                                                         &page_size, &addr_size, &values, &filenames);
-
-                       int ii;
-                       for (ii = 0; ii < values_cnt; ii++) {
-                               uint64_t mapping_start = 0, mapping_end = 0, offset_in_pages = 0;
-                               const char *item = values + 3 * addr_size * ii;
-
-                               __get_mapping_item(core, addr_size, item, &mapping_start, &mapping_end,
-                                                                &offset_in_pages);
-
-                               if (mapping_start <= proc_info->addr && proc_info->addr < mapping_end) {
-                                       free(proc_info->module_name);
-                                       proc_info->module_name = strdup(filenames);
-                                       __find_symbol_in_elf(proc_info, mapping_start);
-                                       return;
-                               }
-
-                               filenames += strlen(filenames)+1;
-                       }
-               }
-               pos = new_pos;
-       }
-}
-
-/**
  * @brief Checks if symbol starts with '_Z' prefix
  *
  * @param symbol string to compare
@@ -587,16 +431,12 @@ static void __demangle_symbols(ProcInfo *proc_info)
  *
  * @param proc_info gathered call stack element
  * @param dwfl dwfl handler
- * @param core ELF handler for the core dump file, NULL if live process analyzed
  * @param notes notes handler, NULL if live process analyzed
  */
-static void __resolve_symbols(ProcInfo *proc_info, Dwfl *dwfl, Elf *core, Elf_Data *notes)
+static void __resolve_symbols(ProcInfo *proc_info, Dwfl *dwfl)
 {
        __resolve_symbols_from_dwfl(proc_info, dwfl);
 
-       if (core != NULL && (!proc_info->module_name || !proc_info->name))
-               __resolve_symbols_from_elf(proc_info, core, notes);
-
        if (is_symbol_demanglable(proc_info->name))
                __demangle_symbols(proc_info);
 }
@@ -628,13 +468,12 @@ static void __print_proc_info(ProcInfo *proc_info)
  * @brief Prints call stack to the global outputfile.
  *
  * @param callstack gathered call stack database
- * @param pid PID of the live process, 0 if core dump file analyzed
+ * @param pid PID of the live process
  */
 static void __print_callstack(Callstack *callstack, pid_t pid)
 {
        fprintf(outputfile, "\nCallstack Information");
-       if (pid > 1)
-               fprintf(outputfile, " (PID:%d)", pid);
+       fprintf(outputfile, " (PID:%d)", pid);
        fprintf(outputfile, "\nCall Stack Count: %zu\n", callstack->elems);
 
        size_t it;
@@ -963,13 +802,11 @@ static void __crash_stack_print_meminfo(FILE* outputfile, pid_t pid)
 /**
  * @brief Main function.
  *
- * Main module accepts two forms of launching:
+ * Main module accepts should be launched with:
  *
- *     crash-stack core-dump-file
- *     crash-stack --pid pid
+ *     crash-stack --pid pid [--tid tid] [--sig sig]
  *
- * The first form allows user to print call stack of a generated core dump file.
- * The second form allows connecting to a live process and displaying its call stack.
+ * It allows connecting to a live process and displaying its call stack.
  * It might be also used for connecting to a process from system's core dump handler.
  */
 int main(int argc, char **argv)
@@ -1025,11 +862,7 @@ int main(int argc, char **argv)
        if (NULL == dwfl)
                return 1111;
 
-       Mappings mappings;
-       mappings.elems = 0;
-
-       dwfl_getmodules(dwfl, __module_callback, &mappings, 0);
-       Elf_Data *notes = 0;
+       dwfl_getmodules(dwfl, __module_callback, NULL, 0);
 
        /* Executable File Path */
        __crash_stack_print_exe(outputfile, pid);
@@ -1044,10 +877,10 @@ int main(int argc, char **argv)
        Callstack callstack;
        callstack_constructor(&callstack);
 
-       _create_crash_stack(dwfl, NULL, tid, &mappings, &callstack);
+       _create_crash_stack(dwfl, tid, &callstack);
        size_t it;
        for (it = 0; it != callstack.elems; ++it)
-               __resolve_symbols(&callstack.proc[it], dwfl, NULL, notes);
+               __resolve_symbols(&callstack.proc[it], dwfl);
 
        /* Print registers */
        _crash_stack_print_regs(outputfile);
index b35ef3b..0675251 100644 (file)
@@ -50,29 +50,6 @@ struct Callstack {
 typedef struct Callstack Callstack;
 
 /**
- * @brief module mappings database element - a single mapping
- */
-struct Mapping {
-       uintptr_t m_start;                                      ///< start address of the module
-       uintptr_t m_end;                                        ///< end address of the module
-       uintptr_t m_offset;                                     ///< offset in core file
-       const char *m_name;                                     ///< file name of the module
-       int m_fd;                                                       ///< file descriptor, filled if already open
-       Elf *m_elf;                                                     ///< ELF handler, initialized when ELF open with libelf
-};
-typedef struct Mapping Mapping;
-
-#define MAX_MAPPINGS_NUM 1000
-/**
- * @brief module mappings database
- */
-struct Mappings {
-       Mapping tab[MAX_MAPPINGS_NUM];          ///< storage for elements
-       size_t elems;                                           ///< number of elements in the database
-};
-typedef struct Mappings Mappings;
-
-/**
  * @brief Gets address of storage for specified register value
  *
  * @remarks This function uses static storage. Thus, it shouldn't be used in multiple threads.
@@ -87,38 +64,10 @@ void *_get_place_for_register_value(const char *regname, int regnum);
  * @brief Creates call stack database.
  *
  * @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 pid pid of the analyzed process
  * @param callstack pointer to call stack database; results are put here
  */
-void _create_crash_stack(Dwfl *dwfl, Elf *core, pid_t pid, Mappings *mappings, Callstack *callstack);
-
-/**
- * @brief Tries to find address of the prologue of the function specified by some address.
- *
- * @param dwfl dwfl handle
- * @param current_pc some address from a function
- * @param mappings module mappings database
- * @return address of the found prologue of the function, NULL if not found
- */
-Dwarf_Addr _crash_stack_libelf_get_prologue_pc(Dwfl *dwfl, Dwarf_Addr current_pc, Mappings *mappings);
-
-/**
- * @brief Reads a value from specified address from target's address space.
- *
- * @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 a address to read from
- * @param[out] v allocated memory to copy value to
- * @param size size of the value to copy
- * @param mappings module mappings database
- * @return true on success, false otherwise
- */
-bool _crash_stack_libelf_read_value(Dwfl *dwfl, Elf *core, pid_t pid,
-                                                                       Dwarf_Addr a, void *v, size_t size,
-                                                                       Mappings *mappings);
+void _create_crash_stack(Dwfl *dwfl, pid_t pid, Callstack *callstack);
 
 /**
  * @brief Gets allocated space for getting target registers with ptrace().