From: Adrian Szyndela Date: Mon, 2 Jan 2017 14:03:58 +0000 (+0100) Subject: crash-stack: remove the core dump handling remains X-Git-Tag: accepted/tizen/3.0/common/20170222.125537~8 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a65fb9f013cf34e8d74dac8467fcc6b71171d688;p=platform%2Fcore%2Fsystem%2Fcrash-worker.git crash-stack: remove the core dump handling remains Hopefully, there is no more rotting flesh. Change-Id: I59003e8a38dd2817f78d23319848273615a0a5be --- diff --git a/src/crash-stack/CMakeLists.txt b/src/crash-stack/CMakeLists.txt index 807d898..77ff0ce 100644 --- a/src/crash-stack/CMakeLists.txt +++ b/src/crash-stack/CMakeLists.txt @@ -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 index 8239a05..0000000 --- a/src/crash-stack/crash-stack-libelf-helpers.c +++ /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 - */ -/** - * @file crash-stack-libelf-helpers.c - * @brief unwinding call stacks, functions for accessing libelf for other - * purposes than unwinding - */ -#include "crash-stack.h" -#include -#include -#include - -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; -} diff --git a/src/crash-stack/crash-stack-libunw.c b/src/crash-stack/crash-stack-libunw.c index b9b9c35..544a3e4 100644 --- a/src/crash-stack/crash-stack-libunw.c +++ b/src/crash-stack/crash-stack-libunw.c @@ -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; diff --git a/src/crash-stack/crash-stack.c b/src/crash-stack/crash-stack.c index 142b247..00d19b6 100644 --- a/src/crash-stack/crash-stack.c +++ b/src/crash-stack/crash-stack.c @@ -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 @@ -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 - * 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); diff --git a/src/crash-stack/crash-stack.h b/src/crash-stack/crash-stack.h index b35ef3b..0675251 100644 --- a/src/crash-stack/crash-stack.h +++ b/src/crash-stack/crash-stack.h @@ -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().