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