From ffa9646749ec8c8c39873b0183cd7cebca1c7319 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sun, 10 Nov 2019 20:01:19 +0300 Subject: [PATCH] Revert "print_backtrace_skipping_top_frames: Implementation for MSVC " This reverts commit d1e7a54f3a2984c09e491d087de21af838b8faad. --- vlib/builtin/builtin.v | 53 +++++++++-- vlib/builtin/builtin_nix.v | 77 ---------------- vlib/builtin/builtin_windows.v | 127 --------------------------- vlib/compiler/cheaders.v | 1 - vlib/compiler/msvc.v | 2 +- vlib/compiler/tests/backtrace_test.v | 11 --- vlib/os/os_windows.v | 1 + 7 files changed, 46 insertions(+), 226 deletions(-) delete mode 100644 vlib/builtin/builtin_nix.v delete mode 100644 vlib/builtin/builtin_windows.v delete mode 100644 vlib/compiler/tests/backtrace_test.v diff --git a/vlib/builtin/builtin.v b/vlib/builtin/builtin.v index aef052fb13..3cac11d0bd 100644 --- a/vlib/builtin/builtin.v +++ b/vlib/builtin/builtin.v @@ -31,20 +31,55 @@ fn on_panic(f fn (int) int) { } pub fn print_backtrace_skipping_top_frames(skipframes int) { - $if windows { - $if msvc { - if print_backtrace_skipping_top_frames_msvc(skipframes) { return } + $if mac { + buffer := [100]byteptr + nr_ptrs := C.backtrace(*voidptr(buffer), 100) + C.backtrace_symbols_fd(*voidptr(&buffer[skipframes]), nr_ptrs-skipframes, 1) + return + } + $if linux { + $if !android { + $if glibc { + // backtrace is not available on Android. + //if C.backtrace_symbols_fd != 0 { + buffer := [100]byteptr + nr_ptrs := C.backtrace(*voidptr(buffer), 100) + nr_actual_frames := nr_ptrs-skipframes + mut sframes := []string + csymbols := *byteptr(C.backtrace_symbols(*voidptr(&buffer[skipframes]), nr_actual_frames)) + for i in 0..nr_actual_frames { sframes << tos2(csymbols[i]) } + for sframe in sframes { + executable := sframe.all_before('(') + addr := sframe.all_after('[').all_before(']') + cmd := 'addr2line -e $executable $addr' + + // taken from os, to avoid depending on the os module inside builtin.v + f := C.popen(cmd.str, 'r') + if isnil(f) { + println(sframe) continue + } + buf := [1000]byte + mut output := '' + for C.fgets(voidptr(buf), 1000, f) != 0 { + output += tos(buf, vstrlen(buf)) + } + output = output.trim_space()+':' + if 0 != int(C.pclose(f)) { + println(sframe) continue + } + println( '${output:-45s} | $sframe') + } + //C.backtrace_symbols_fd(*voidptr(&buffer[skipframes]), nr_actual_frames, 1) + return + }$else{ + C.printf('backtrace_symbols_fd is missing, so printing backtraces is not available.\n') + C.printf('Some libc implementations like musl simply do not provide it.\n') + } } - $if mingw { - if print_backtrace_skipping_top_frames_mingw(skipframes) { return } - } - }$else{ - if print_backtrace_skipping_top_frames_nix(skipframes) { return } } println('print_backtrace_skipping_top_frames is not implemented on this platform for now...\n') } - pub fn print_backtrace(){ // at the time of backtrace_symbols_fd call, the C stack would look something like this: // 1 frame for print_backtrace_skipping_top_frames diff --git a/vlib/builtin/builtin_nix.v b/vlib/builtin/builtin_nix.v deleted file mode 100644 index 5105f390ba..0000000000 --- a/vlib/builtin/builtin_nix.v +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. -// Use of this source code is governed by an MIT license -// that can be found in the LICENSE file. - -module builtin - -fn print_backtrace_skipping_top_frames_msvc(skipframes int) bool { - println('not implemented, see builtin_windows.v') - return false -} - -fn print_backtrace_skipping_top_frames_mingw(skipframes int) bool { - println('not implemented, see builtin_windows.v') - return false -} - -fn print_backtrace_skipping_top_frames_nix(xskipframes int) bool { - skipframes := xskipframes + 2 - $if mac { return print_backtrace_skipping_top_frames_mac(skipframes) } - $if linux { return print_backtrace_skipping_top_frames_linux(skipframes) } - return false -} - -// the functions below are not called outside this file, -// so there is no need to have their twins in builtin_windows.v -fn print_backtrace_skipping_top_frames_mac(skipframes int) bool { - buffer := [100]byteptr - nr_ptrs := C.backtrace(*voidptr(buffer), 100) - C.backtrace_symbols_fd(*voidptr(&buffer[skipframes]), nr_ptrs-skipframes, 1) - return true -} - -fn print_backtrace_skipping_top_frames_linux(skipframes int) bool { - $if tinyc { - println('TODO: print_backtrace_skipping_top_frames_linux $skipframes with tcc fails tests with "stack smashing detected" .') - return false - } - $if !android { - $if glibc { - // backtrace is not available on Android. - //if C.backtrace_symbols_fd != 0 { - buffer := [100]byteptr - nr_ptrs := C.backtrace(*voidptr(buffer), 100) - nr_actual_frames := nr_ptrs-skipframes - mut sframes := []string - csymbols := *byteptr(C.backtrace_symbols(*voidptr(&buffer[skipframes]), nr_actual_frames)) - for i in 0..nr_actual_frames { sframes << tos2(csymbols[i]) } - for sframe in sframes { - executable := sframe.all_before('(') - addr := sframe.all_after('[').all_before(']') - cmd := 'addr2line -e $executable $addr' - - // taken from os, to avoid depending on the os module inside builtin.v - f := C.popen(cmd.str, 'r') - if isnil(f) { - println(sframe) continue - } - buf := [1000]byte - mut output := '' - for C.fgets(voidptr(buf), 1000, f) != 0 { - output += tos(buf, vstrlen(buf)) - } - output = output.trim_space()+':' - if 0 != int(C.pclose(f)) { - println(sframe) continue - } - println( '${output:-45s} | $sframe') - } - //C.backtrace_symbols_fd(*voidptr(&buffer[skipframes]), nr_actual_frames, 1) - return true - }$else{ - C.printf('backtrace_symbols_fd is missing, so printing backtraces is not available.\n') - C.printf('Some libc implementations like musl simply do not provide it.\n') - } - } - return false -} diff --git a/vlib/builtin/builtin_windows.v b/vlib/builtin/builtin_windows.v deleted file mode 100644 index 48291332dd..0000000000 --- a/vlib/builtin/builtin_windows.v +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. -// Use of this source code is governed by an MIT license -// that can be found in the LICENSE file. - -module builtin - -#include -#flag windows -l dbghelp - -pub struct SymbolInfo { -pub mut: - f_size_of_struct u32 // must be 88 to be recognised by SymFromAddr - f_type_index u32 // Type Index of symbol - f_reserved [2]u64 - f_index u32 - f_size u32 - f_mod_base u64 // Base Address of module comtaining this symbol - f_flags u32 - f_value u64 // Value of symbol, ValuePresent should be 1 - f_address u64 // Address of symbol including base address of module - f_register u32 // register holding value or pointer to value - f_scope u32 // scope of the symbol - f_tag u32 // pdb classification - f_name_len u32 // Actual length of name - f_max_name_len u32 // must be manually set - f_name byte // must be calloc(f_max_name_len) -} - -pub struct SymbolInfoContainer { -pub mut: - syminfo SymbolInfo - f_name_rest [254]char -} - -pub struct Line64 { - f_size_of_struct u32 - f_key voidptr - f_line_number u32 - f_file_name byteptr - f_address u64 -} - -fn C.SymSetOptions(symoptions u32) u32 // returns the current options mask -fn C.GetCurrentProcess() voidptr // returns handle -fn C.SymInitialize(h_process voidptr, p_user_search_path byteptr, b_invade_process int) int -fn C.CaptureStackBackTrace(frames_to_skip u32, frames_to_capture u32, p_backtrace voidptr, p_backtrace_hash voidptr) u16 -fn C.SymFromAddr(h_process voidptr, address u64, p_displacement voidptr, p_symbol voidptr) int -fn C.SymGetLineFromAddr64(h_process voidptr, address u64, p_displacement voidptr, p_line &Line64) int - -// Ref - https://docs.microsoft.com/en-us/windows/win32/api/dbghelp/nf-dbghelp-symsetoptions -const ( - SYMOPT_UNDNAME = 0x00000002 - SYMOPT_DEFERRED_LOADS = 0x00000004 - SYMOPT_NO_CPP = 0x00000008 - SYMOPT_LOAD_LINES = 0x00000010 - SYMOPT_INCLUDE_32BIT_MODULES = 0x00002000 - SYMOPT_ALLOW_ZERO_ADDRESS = 0x01000000 - SYMOPT_DEBUG = 0x80000000 -) - -fn print_backtrace_skipping_top_frames_msvc(skipframes int) bool { - mut offset := u64(0) - backtraces := [100]voidptr - sic := SymbolInfoContainer{} - mut si := &sic.syminfo - si.f_size_of_struct = sizeof(SymbolInfo) // Note: C.SYMBOL_INFO is 88 - si.f_max_name_len = sizeof(SymbolInfoContainer) - sizeof(SymbolInfo) - 1 - fname := *char( &si.f_name ) - mut sline64 := Line64{} - sline64.f_size_of_struct = sizeof(Line64) - - handle := C.GetCurrentProcess() - defer { C.SymCleanup(handle) } - - options := C.SymSetOptions(SYMOPT_DEBUG | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME) - syminitok := C.SymInitialize( handle, 0, 1) - if syminitok != 1 { - println('Failed getting process: Aborting backtrace.\n') - return true - } - - frames := int( C.CaptureStackBackTrace(skipframes + 1, 100, backtraces, 0) ) - for i:=0; i < frames; i++ { - // fugly pointer arithmetics follows ... - s := *voidptr( u64(backtraces) + u64(i*sizeof(voidptr)) ) - symfa_ok := C.SymFromAddr( handle, *s, &offset, si ) - if symfa_ok == 1 { - nframe := frames - i - 1 - mut lineinfo := '' - symglfa_ok := C.SymGetLineFromAddr64(handle, *s, &offset, &sline64) - if symglfa_ok == 1 { - lineinfo = ' ${sline64.f_file_name}:${sline64.f_line_number}' - } - else { - //cerr := int(C.GetLastError()) println('SymGetLineFromAddr64 failure: $cerr ') - lineinfo = ' ?? : address= $s' - } - sfunc := tos3(fname) - println('${nframe:-2d}: ${sfunc:-25s} $lineinfo') - } - else { - // https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes - cerr := int(C.GetLastError()) - if (cerr == 87) { - println('SymFromAddr failure: $cerr = The parameter is incorrect)') - } - else if (cerr == 487) { - // probably caused because the .pdb isn't in the executable folder - println('SymFromAddr failure: $cerr = Attempt to access invalid address (Verify that you have the .pdb file in the right folder.)') - } - else { - println('SymFromAddr failure: $cerr (see https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes)') - } - } - } - return true -} - -fn print_backtrace_skipping_top_frames_mingw(skipframes int) bool { - println('TODO: print_backtrace_skipping_top_frames_mingw($skipframes)') - return false -} - -fn print_backtrace_skipping_top_frames_nix(skipframes int) bool { - println('not implemented, see builtin_nix.v') - return false -} diff --git a/vlib/compiler/cheaders.v b/vlib/compiler/cheaders.v index c35c4cb0fa..8172c77dd6 100644 --- a/vlib/compiler/cheaders.v +++ b/vlib/compiler/cheaders.v @@ -19,7 +19,6 @@ CommonCHeaders = ' #include #include // sleep #else -#pragma comment(lib, "Dbghelp.lib") #if defined(__MSVCRT_VERSION__) && __MSVCRT_VERSION__ < __MSVCR90_DLL #error Please upgrade your MinGW distribution to use msvcr90.dll or later. #endif diff --git a/vlib/compiler/msvc.v b/vlib/compiler/msvc.v index ef29b66d1d..512f06873a 100644 --- a/vlib/compiler/msvc.v +++ b/vlib/compiler/msvc.v @@ -3,7 +3,7 @@ module compiler import os #flag windows -l shell32 -#flag windows -l dbghelp + // RegOpenKeyExA etc #flag windows -l advapi32 diff --git a/vlib/compiler/tests/backtrace_test.v b/vlib/compiler/tests/backtrace_test.v deleted file mode 100644 index 32509445c1..0000000000 --- a/vlib/compiler/tests/backtrace_test.v +++ /dev/null @@ -1,11 +0,0 @@ -/* - Test for backtrace capability -*/ -fn a_method() { - print_backtrace() -} - -fn test_backtrace() { - a_method() - //panic('hi') -} diff --git a/vlib/os/os_windows.v b/vlib/os/os_windows.v index 9fb5219270..aaf7738b82 100644 --- a/vlib/os/os_windows.v +++ b/vlib/os/os_windows.v @@ -86,6 +86,7 @@ fn init_os_args(argc int, argv &byteptr) []string { return args } + pub fn ls(path string) ?[]string { mut find_file_data := Win32finddata{} mut dir_files := []string