From 1b4032c74e36dfdbb2ba0063796dd7c2b924babd Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Wed, 22 Nov 2017 08:05:36 +0300 Subject: Explore possibility of supporting mingw --- mysql/mysys/stacktrace.c | 802 ----------------------------------------------- 1 file changed, 802 deletions(-) delete mode 100644 mysql/mysys/stacktrace.c (limited to 'mysql/mysys/stacktrace.c') diff --git a/mysql/mysys/stacktrace.c b/mysql/mysys/stacktrace.c deleted file mode 100644 index f4fe6c8..0000000 --- a/mysql/mysys/stacktrace.c +++ /dev/null @@ -1,802 +0,0 @@ -/* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "my_stacktrace.h" - -#ifndef _WIN32 -#include "my_thread.h" -#include "m_string.h" -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_STACKTRACE - -#ifdef __linux__ -#include /* isprint */ -#include /* SYS_gettid */ -#endif - -#if HAVE_EXECINFO_H -#include -#endif - -#ifdef __linux__ -/* __bss_start doesn't seem to work on FreeBSD and doesn't exist on OSX/Solaris. */ -#define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end) -static char *heap_start; -extern char *__bss_start; -#else -#define PTR_SANE(p) (p) -#endif /* __linux */ - -void my_init_stacktrace() -{ -#ifdef __linux__ - heap_start = (char*) &__bss_start; -#endif /* __linux__ */ -} - -#ifdef __linux__ - -static void print_buffer(char *buffer, size_t count) -{ - const char s[]= " "; - for (; count && *buffer; --count) - { - my_write_stderr(isprint(*buffer) ? buffer : s, 1); - ++buffer; - } -} - -/** - Access the pages of this process through /proc/self/task//mem - in order to safely print the contents of a memory address range. - - @param addr The address at the start of the memory region. - @param max_len The length of the memory region. - - @return Zero on success. -*/ -static int safe_print_str(const char *addr, int max_len) -{ - int fd; - pid_t tid; - off_t offset; - ssize_t nbytes= 0; - size_t total, count; - char buf[256]; - - tid= (pid_t) syscall(SYS_gettid); - - sprintf(buf, "/proc/self/task/%d/mem", tid); - - if ((fd= open(buf, O_RDONLY)) < 0) - return -1; - - /* Ensure that off_t can hold a pointer. */ - compile_time_assert(sizeof(off_t) >= sizeof(intptr)); - - total= max_len; - offset= (intptr) addr; - - /* Read up to the maximum number of bytes. */ - while (total) - { - count= MY_MIN(sizeof(buf), total); - - if ((nbytes= pread(fd, buf, count, offset)) < 0) - { - /* Just in case... */ - if (errno == EINTR) - continue; - else - break; - } - - /* Advance offset into memory. */ - total-= nbytes; - offset+= nbytes; - addr+= nbytes; - - /* Output the printable characters. */ - print_buffer(buf, nbytes); - - /* Break if less than requested... */ - if ((count - nbytes)) - break; - } - - /* Output a new line if something was printed. */ - if (total != (size_t) max_len) - my_safe_printf_stderr("%s", "\n"); - - if (nbytes == -1) - my_safe_printf_stderr("Can't read from address %p\n", addr); - - close(fd); - - return 0; -} - -#endif /* __linux __ */ - -void my_safe_puts_stderr(const char* val, size_t max_len) -{ -#ifdef __linux__ -/* Only needed by the linux version of PTR_SANE */ - char *heap_end; - - if (!safe_print_str(val, max_len)) - return; - - heap_end= (char*) sbrk(0); -#endif - - if (!PTR_SANE(val)) - { - my_safe_printf_stderr("%s", "is an invalid pointer\n"); - return; - } - - for (; max_len && PTR_SANE(val) && *val; --max_len) - my_write_stderr((val++), 1); - my_safe_printf_stderr("%s", "\n"); -} - -#if defined(HAVE_PRINTSTACK) - -/* Use Solaris' symbolic stack trace routine. */ -#include - -void my_print_stacktrace(uchar* stack_bottom MY_ATTRIBUTE((unused)), - ulong thread_stack MY_ATTRIBUTE((unused))) -{ - if (printstack(fileno(stderr)) == -1) - my_safe_printf_stderr("%s", - "Error when traversing the stack, stack appears corrupt.\n"); - else - my_safe_printf_stderr("Please read " - "http://dev.mysql.com/doc/refman/%u.%u/en/resolve-stack-dump.html\n" - "and follow instructions on how to resolve the stack trace.\n" - "Resolved stack trace is much more helpful in diagnosing the\n" - "problem, so please do resolve it\n", - MYSQL_VERSION_MAJOR, MYSQL_VERSION_MINOR); -} - -#elif HAVE_BACKTRACE - -#if HAVE_ABI_CXA_DEMANGLE - -char MY_ATTRIBUTE ((weak)) * -my_demangle(const char *mangled_name MY_ATTRIBUTE((unused)), - int *status MY_ATTRIBUTE((unused))) -{ - return NULL; -} - -static void my_demangle_symbols(char **addrs, int n) -{ - int status, i; - char *begin, *end, *demangled; - - for (i= 0; i < n; i++) - { - demangled= NULL; - begin= strchr(addrs[i], '('); - end= begin ? strchr(begin, '+') : NULL; - - if (begin && end) - { - *begin++= *end++= '\0'; - demangled= my_demangle(begin, &status); - if (!demangled || status) - { - demangled= NULL; - begin[-1]= '('; - end[-1]= '+'; - } - } - - if (demangled) - my_safe_printf_stderr("%s(%s+%s\n", addrs[i], demangled, end); - else - my_safe_printf_stderr("%s\n", addrs[i]); - } -} - -#endif /* HAVE_ABI_CXA_DEMANGLE */ - -void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack) -{ - void *addrs[128]; - char **strings= NULL; - int n = backtrace(addrs, array_elements(addrs)); - my_safe_printf_stderr("stack_bottom = %p thread_stack 0x%lx\n", - stack_bottom, thread_stack); -#if HAVE_ABI_CXA_DEMANGLE - if ((strings= backtrace_symbols(addrs, n))) - { - my_demangle_symbols(strings, n); - free(strings); - } -#endif - if (!strings) - { - backtrace_symbols_fd(addrs, n, fileno(stderr)); - } -} - -#endif /* HAVE_PRINTSTACK || HAVE_BACKTRACE */ -#endif /* HAVE_STACKTRACE */ - -/* Produce a core for the thread */ -void my_write_core(int sig) -{ - signal(sig, SIG_DFL); - pthread_kill(my_thread_self(), sig); -#if defined(P_MYID) - /* On Solaris, the above kill is not enough */ - sigsend(P_PID,P_MYID,sig); -#endif -} - -#else /* _WIN32*/ - -#include -#include -#if _MSC_VER -#pragma comment(lib, "dbghelp") -#endif - -static EXCEPTION_POINTERS *exception_ptrs; - -#define MODULE64_SIZE_WINXP 576 -#define STACKWALK_MAX_FRAMES 64 - -void my_init_stacktrace() -{ -} - - -void my_set_exception_pointers(EXCEPTION_POINTERS *ep) -{ - exception_ptrs = ep; -} - -/* - Appends directory to symbol path. -*/ -static void add_to_symbol_path(char *path, size_t path_buffer_size, - char *dir, size_t dir_buffer_size) -{ - strcat_s(dir, dir_buffer_size, ";"); - if (!strstr(path, dir)) - { - strcat_s(path, path_buffer_size, dir); - } -} - -/* - Get symbol path - semicolon-separated list of directories to search for debug - symbols. We expect PDB in the same directory as corresponding exe or dll, - so the path is build from directories of the loaded modules. If environment - variable _NT_SYMBOL_PATH is set, it's value appended to the symbol search path -*/ -static void get_symbol_path(char *path, size_t size) -{ - HANDLE hSnap; - char *envvar; - char *p; -#ifndef DBUG_OFF - static char pdb_debug_dir[MAX_PATH + 7]; -#endif - - path[0]= '\0'; - -#ifndef DBUG_OFF - /* - Add "debug" subdirectory of the application directory, sometimes PDB will - placed here by installation. - */ - GetModuleFileName(NULL, pdb_debug_dir, MAX_PATH); - p= strrchr(pdb_debug_dir, '\\'); - if(p) - { - *p= 0; - strcat_s(pdb_debug_dir, sizeof(pdb_debug_dir), "\\debug;"); - add_to_symbol_path(path, size, pdb_debug_dir, sizeof(pdb_debug_dir)); - } -#endif - - /* - Enumerate all modules, and add their directories to the path. - Avoid duplicate entries. - */ - hSnap= CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); - if (hSnap != INVALID_HANDLE_VALUE) - { - BOOL ret; - MODULEENTRY32 mod; - mod.dwSize= sizeof(MODULEENTRY32); - for (ret= Module32First(hSnap, &mod); ret; ret= Module32Next(hSnap, &mod)) - { - char *module_dir= mod.szExePath; - p= strrchr(module_dir,'\\'); - if (!p) - { - /* - Path separator was not found. Not known to happen, if ever happens, - will indicate current directory. - */ - module_dir[0]= '.'; - module_dir[1]= '\0'; - } - else - { - *p= '\0'; - } - add_to_symbol_path(path, size, module_dir,sizeof(mod.szExePath)); - } - CloseHandle(hSnap); - } - - - /* Add _NT_SYMBOL_PATH, if present. */ - envvar= getenv("_NT_SYMBOL_PATH"); - if(envvar) - { - strcat_s(path, size, envvar); - } -} - -#define MAX_SYMBOL_PATH 32768 - -/* Platform SDK in VS2003 does not have definition for SYMOPT_NO_PROMPTS*/ -#ifndef SYMOPT_NO_PROMPTS -#define SYMOPT_NO_PROMPTS 0 -#endif - -void my_print_stacktrace(uchar* unused1, ulong unused2) -{ - HANDLE hProcess= GetCurrentProcess(); - HANDLE hThread= GetCurrentThread(); - static IMAGEHLP_MODULE64 module= {sizeof(module)}; - static IMAGEHLP_SYMBOL64_PACKAGE package; - DWORD64 addr; - DWORD machine; - int i; - CONTEXT context; - STACKFRAME64 frame={0}; - static char symbol_path[MAX_SYMBOL_PATH]; - - if(!exception_ptrs) - return; - - /* Copy context, as stackwalking on original will unwind the stack */ - context = *(exception_ptrs->ContextRecord); - /*Initialize symbols.*/ - SymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_NO_PROMPTS|SYMOPT_DEFERRED_LOADS|SYMOPT_DEBUG); - get_symbol_path(symbol_path, sizeof(symbol_path)); - SymInitialize(hProcess, symbol_path, TRUE); - - /*Prepare stackframe for the first StackWalk64 call*/ - frame.AddrFrame.Mode= frame.AddrPC.Mode= frame.AddrStack.Mode= AddrModeFlat; -#if (defined _M_IX86) - machine= IMAGE_FILE_MACHINE_I386; - frame.AddrFrame.Offset= context.Ebp; - frame.AddrPC.Offset= context.Eip; - frame.AddrStack.Offset= context.Esp; -#elif (defined _M_X64) - machine = IMAGE_FILE_MACHINE_AMD64; - frame.AddrFrame.Offset= context.Rbp; - frame.AddrPC.Offset= context.Rip; - frame.AddrStack.Offset= context.Rsp; -#else - /*There is currently no need to support IA64*/ -#pragma error ("unsupported architecture") -#endif - - package.sym.SizeOfStruct= sizeof(package.sym); - package.sym.MaxNameLength= sizeof(package.name); - - /*Walk the stack, output useful information*/ - for(i= 0; i< STACKWALK_MAX_FRAMES;i++) - { - DWORD64 function_offset= 0; - DWORD line_offset= 0; - IMAGEHLP_LINE64 line= {sizeof(line)}; - BOOL have_module= FALSE; - BOOL have_symbol= FALSE; - BOOL have_source= FALSE; - - if(!StackWalk64(machine, hProcess, hThread, &frame, &context, 0, 0, 0 ,0)) - break; - addr= frame.AddrPC.Offset; - - have_module= SymGetModuleInfo64(hProcess,addr,&module); -#ifdef _M_IX86 - if(!have_module) - { - /* - ModuleInfo structure has been "compatibly" extended in releases after XP, - and its size was increased. To make XP dbghelp.dll function - happy, pretend passing the old structure. - */ - module.SizeOfStruct= MODULE64_SIZE_WINXP; - have_module= SymGetModuleInfo64(hProcess, addr, &module); - } -#endif - - have_symbol= SymGetSymFromAddr64(hProcess, addr, &function_offset, - &(package.sym)); - have_source= SymGetLineFromAddr64(hProcess, addr, &line_offset, &line); - - my_safe_printf_stderr("%p ", addr); - if(have_module) - { - char *base_image_name= strrchr(module.ImageName, '\\'); - if(base_image_name) - base_image_name++; - else - base_image_name= module.ImageName; - my_safe_printf_stderr("%s!", base_image_name); - } - if(have_symbol) - my_safe_printf_stderr("%s()", package.sym.Name); - - else if(have_module) - my_safe_printf_stderr("%s", "???"); - - if(have_source) - { - char *base_file_name= strrchr(line.FileName, '\\'); - if(base_file_name) - base_file_name++; - else - base_file_name= line.FileName; - my_safe_printf_stderr("[%s:%u]", - base_file_name, line.LineNumber); - } - my_safe_printf_stderr("%s", "\n"); - } -} - - -/* - Write dump. The dump is created in current directory, - file name is constructed from executable name plus - ".dmp" extension -*/ -void my_write_core(int unused) -{ - char path[MAX_PATH]; - char dump_fname[MAX_PATH]= "core.dmp"; - - if(!exception_ptrs) - return; - - if(GetModuleFileName(NULL, path, sizeof(path))) - { - _splitpath(path, NULL, NULL,dump_fname,NULL); - strncat(dump_fname, ".dmp", sizeof(dump_fname)); - } - my_create_minidump(dump_fname, 0, 0); -} - - -/** Create a minidump. - @param name path of minidump file. - @param process HANDLE to process. (0 for own process). - @param pid Process id. -*/ - -void my_create_minidump(const char *name, HANDLE process, DWORD pid) -{ - char path[MAX_PATH]; - MINIDUMP_EXCEPTION_INFORMATION info; - HANDLE hFile; - - if (process == 0) - { - /* Does not need to CloseHandle() for the below. */ - process= GetCurrentProcess(); - pid= GetCurrentProcessId(); - info.ExceptionPointers= exception_ptrs; - info.ClientPointers= FALSE; - info.ThreadId= GetCurrentThreadId(); - } - - hFile= CreateFile(name, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, 0); - if(hFile) - { - MINIDUMP_TYPE mdt= (MINIDUMP_TYPE) (MiniDumpNormal | - MiniDumpWithThreadInfo | - MiniDumpWithProcessThreadData); - /* Create minidump, use info only if same process. */ - if(MiniDumpWriteDump(process, pid, hFile, mdt, - process ? NULL : &info, 0, 0)) - { - my_safe_printf_stderr("Minidump written to %s\n", - _fullpath(path, name, sizeof(path)) ? - path : name); - } - else - { - my_safe_printf_stderr("MiniDumpWriteDump() failed, last error %d\n", - GetLastError()); - } - CloseHandle(hFile); - } - else - { - my_safe_printf_stderr("CreateFile(%s) failed, last error %d\n", - name, GetLastError()); - } -} - - -void my_safe_puts_stderr(const char *val, size_t len) -{ - __try - { - my_write_stderr(val, len); - my_safe_printf_stderr("%s", "\n"); - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - my_safe_printf_stderr("%s", "is an invalid string pointer\n"); - } -} -#endif /* _WIN32 */ - - -#ifdef _WIN32 -size_t my_write_stderr(const void *buf, size_t count) -{ - DWORD bytes_written; - SetFilePointer(GetStdHandle(STD_ERROR_HANDLE), 0, NULL, FILE_END); - WriteFile(GetStdHandle(STD_ERROR_HANDLE), buf, (DWORD)count, &bytes_written, NULL); - return bytes_written; -} -#else -size_t my_write_stderr(const void *buf, size_t count) -{ - return (size_t) write(STDERR_FILENO, buf, count); -} -#endif - - -static const char digits[]= "0123456789abcdef"; - -char *my_safe_utoa(int base, ulonglong val, char *buf) -{ - *buf--= 0; - do { - *buf--= digits[val % base]; - } while ((val /= base) != 0); - return buf + 1; -} - - -char *my_safe_itoa(int base, longlong val, char *buf) -{ - char *orig_buf= buf; - const my_bool is_neg= (val < 0); - *buf--= 0; - - if (is_neg) - val= -val; - if (is_neg && base == 16) - { - int ix; - val-= 1; - for (ix= 0; ix < 16; ++ix) - buf[-ix]= '0'; - } - - do { - *buf--= digits[val % base]; - } while ((val /= base) != 0); - - if (is_neg && base == 10) - *buf--= '-'; - - if (is_neg && base == 16) - { - int ix; - buf= orig_buf - 1; - for (ix= 0; ix < 16; ++ix, --buf) - { - switch (*buf) - { - case '0': *buf= 'f'; break; - case '1': *buf= 'e'; break; - case '2': *buf= 'd'; break; - case '3': *buf= 'c'; break; - case '4': *buf= 'b'; break; - case '5': *buf= 'a'; break; - case '6': *buf= '9'; break; - case '7': *buf= '8'; break; - case '8': *buf= '7'; break; - case '9': *buf= '6'; break; - case 'a': *buf= '5'; break; - case 'b': *buf= '4'; break; - case 'c': *buf= '3'; break; - case 'd': *buf= '2'; break; - case 'e': *buf= '1'; break; - case 'f': *buf= '0'; break; - } - } - } - return buf+1; -} - - -static const char *check_longlong(const char *fmt, my_bool *have_longlong) -{ - *have_longlong= FALSE; - if (*fmt == 'l') - { - fmt++; - if (*fmt != 'l') - *have_longlong= (sizeof(long) == sizeof(longlong)); - else - { - fmt++; - *have_longlong= TRUE; - } - } - return fmt; -} - -static size_t my_safe_vsnprintf(char *to, size_t size, - const char* format, va_list ap) -{ - char *start= to; - char *end= start + size - 1; - for (; *format; ++format) - { - my_bool have_longlong = FALSE; - if (*format != '%') - { - if (to == end) /* end of buffer */ - break; - *to++= *format; /* copy ordinary char */ - continue; - } - ++format; /* skip '%' */ - - format= check_longlong(format, &have_longlong); - - switch (*format) - { - case 'd': - case 'i': - case 'u': - case 'x': - case 'p': - { - longlong ival= 0; - ulonglong uval = 0; - if (*format == 'p') - have_longlong= (sizeof(void *) == sizeof(longlong)); - if (have_longlong) - { - if (*format == 'u') - uval= va_arg(ap, ulonglong); - else - ival= va_arg(ap, longlong); - } - else - { - if (*format == 'u') - uval= va_arg(ap, unsigned int); - else - ival= va_arg(ap, int); - } - - { - char buff[22]; - const int base= (*format == 'x' || *format == 'p') ? 16 : 10; - char *val_as_str= (*format == 'u') ? - my_safe_utoa(base, uval, &buff[sizeof(buff)-1]) : - my_safe_itoa(base, ival, &buff[sizeof(buff)-1]); - - /* - Strip off "ffffffff" if we have 'x' format without 'll' - Similarly for 'p' format on 32bit systems. - */ - if (base == 16 && !have_longlong && ival < 0) - val_as_str+= 8; - - while (*val_as_str && to < end) - *to++= *val_as_str++; - continue; - } - } - case 's': - { - const char *val= va_arg(ap, char*); - if (!val) - val= "(null)"; - while (*val && to < end) - *to++= *val++; - continue; - } - } - } - *to= 0; - return to - start; -} - - -size_t my_safe_snprintf(char* to, size_t n, const char* fmt, ...) -{ - size_t result; - va_list args; - va_start(args,fmt); - result= my_safe_vsnprintf(to, n, fmt, args); - va_end(args); - return result; -} - - -size_t my_safe_printf_stderr(const char* fmt, ...) -{ - char to[512]; - size_t result; - va_list args; - va_start(args,fmt); - result= my_safe_vsnprintf(to, sizeof(to), fmt, args); - va_end(args); - my_write_stderr(to, result); - return result; -} - - -void my_safe_print_system_time() -{ - char hrs_buf[3]= "00"; - char mins_buf[3]= "00"; - char secs_buf[3]= "00"; - int base= 10; -#ifdef _WIN32 - SYSTEMTIME utc_time; - long hrs, mins, secs; - GetSystemTime(&utc_time); - hrs= utc_time.wHour; - mins= utc_time.wMinute; - secs= utc_time.wSecond; -#else - /* Using time() instead of my_time() to avoid looping */ - const time_t curr_time= time(NULL); - /* Calculate time of day */ - const long tmins = curr_time / 60; - const long thrs = tmins / 60; - const long hrs = thrs % 24; - const long mins = tmins % 60; - const long secs = curr_time % 60; -#endif - - my_safe_itoa(base, hrs, &hrs_buf[2]); - my_safe_itoa(base, mins, &mins_buf[2]); - my_safe_itoa(base, secs, &secs_buf[2]); - - my_safe_printf_stderr("---------- %s:%s:%s UTC - ", - hrs_buf, mins_buf, secs_buf); -} - -- cgit v1.1