1// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. 2// Use of this source code is governed by an MIT license 3// that can be found in the LICENSE file. 4module builtin 5 6//pub fn vsyscall(id int 7// 8 9/* 10pub const ( 11 sys_write = 1 12 sys_mkdir = 83 13) 14const ( 15 stdin_value = 0 16 stdout_value = 1 17 stderr_value = 2 18) 19 20*/ 21 22fn builtin_init() { 23 // Do nothing 24} 25 26fn print_backtrace_skipping_top_frames(xskipframes int) bool { 27 skipframes := xskipframes + 2 28 $if macos { 29 return print_backtrace_skipping_top_frames_mac(skipframes) 30 } 31 $if linux { 32 return print_backtrace_skipping_top_frames_linux(skipframes) 33 } 34 $if freebsd { 35 return print_backtrace_skipping_top_frames_freebsd(skipframes) 36 } 37 $if netbsd { 38 return print_backtrace_skipping_top_frames_freebsd(skipframes) 39 } 40 $if openbsd { 41 return print_backtrace_skipping_top_frames_freebsd(skipframes) 42 } 43 println('print_backtrace_skipping_top_frames is not implemented. skipframes: $skipframes') 44 return false 45} 46 47// the functions below are not called outside this file, 48// so there is no need to have their twins in builtin_windows.v 49fn print_backtrace_skipping_top_frames_mac(skipframes int) bool { 50 $if macos { 51 buffer := [100]byteptr 52 nr_ptrs := C.backtrace(buffer, 100) 53 if nr_ptrs < 2 { 54 eprintln('C.backtrace returned less than 2 frames') 55 return false 56 } 57 C.backtrace_symbols_fd(&buffer[skipframes], nr_ptrs - skipframes, 2) 58 } 59 return true 60} 61 62fn print_backtrace_skipping_top_frames_freebsd(skipframes int) bool { 63 $if freebsd { 64 buffer := [100]byteptr 65 nr_ptrs := C.backtrace(buffer, 100) 66 if nr_ptrs < 2 { 67 eprintln('C.backtrace returned less than 2 frames') 68 return false 69 } 70 C.backtrace_symbols_fd(&buffer[skipframes], nr_ptrs - skipframes, 2) 71 } 72 return true 73} 74 75fn C.tcc_backtrace(fmt charptr, other ...charptr) int 76fn print_backtrace_skipping_top_frames_linux(skipframes int) bool { 77 $if android { 78 eprintln('On Android no backtrace is available.') 79 return false 80 } 81 $if !glibc { 82 eprintln('backtrace_symbols is missing => printing backtraces is not available.') 83 eprintln('Some libc implementations like musl simply do not provide it.') 84 return false 85 } 86 $if tinyc { 87 C.tcc_backtrace("Backtrace") 88 return false 89 } 90 buffer := [100]byteptr 91 nr_ptrs := C.backtrace(buffer, 100) 92 if nr_ptrs < 2 { 93 eprintln('C.backtrace returned less than 2 frames') 94 return false 95 } 96 nr_actual_frames := nr_ptrs - skipframes 97 mut sframes := []string{} 98 //////csymbols := backtrace_symbols(*voidptr(&buffer[skipframes]), nr_actual_frames) 99 csymbols := C.backtrace_symbols(&buffer[skipframes], nr_actual_frames) 100 for i in 0 .. nr_actual_frames { 101 sframes << unsafe {tos2( byteptr(csymbols[i]) )} 102 } 103 for sframe in sframes { 104 executable := sframe.all_before('(') 105 addr := sframe.all_after('[').all_before(']') 106 beforeaddr := sframe.all_before('[') 107 cmd := 'addr2line -e $executable $addr' 108 // taken from os, to avoid depending on the os module inside builtin.v 109 f := C.popen(charptr(cmd.str), 'r') 110 if isnil(f) { 111 eprintln(sframe) 112 continue 113 } 114 buf := [1000]byte 115 mut output := '' 116 for C.fgets(charptr(buf), 1000, f) != 0 { 117 output += tos(byteptr(buf), vstrlen(byteptr(buf))) 118 } 119 output = output.trim_space() + ':' 120 if C.pclose(f) != 0 { 121 eprintln(sframe) 122 continue 123 } 124 if output in ['??:0:', '??:?:'] { 125 output = '' 126 } 127 // See http://wiki.dwarfstd.org/index.php?title=Path_Discriminators 128 // NB: it is shortened here to just d. , just so that it fits, and so 129 // that the common error file:lineno: line format is enforced. 130 output = output.replace(' (discriminator', ': (d.') 131 eprintln('${output:-46s} | ${addr:14s} | $beforeaddr') 132 } 133 return true 134} 135 136fn break_if_debugger_attached() { 137 unsafe { 138 mut ptr := &voidptr(0) 139 *ptr = 0 140 } 141} 142