X7ROOT File Manager
Current Path:
/opt/golang/1.22.0/src/runtime
opt
/
golang
/
1.22.0
/
src
/
runtime
/
📁
..
📄
HACKING.md
(13.85 KB)
📄
Makefile
(178 B)
📄
abi_test.go
(2.83 KB)
📄
alg.go
(10.99 KB)
📄
align_runtime_test.go
(1.82 KB)
📄
align_test.go
(5.37 KB)
📄
arena.go
(31.66 KB)
📄
arena_test.go
(13.39 KB)
📁
asan
📄
asan.go
(1.55 KB)
📄
asan0.go
(760 B)
📄
asan_amd64.s
(2.45 KB)
📄
asan_arm64.s
(2.14 KB)
📄
asan_loong64.s
(2.12 KB)
📄
asan_ppc64le.s
(2.75 KB)
📄
asan_riscv64.s
(1.92 KB)
📄
asm.s
(719 B)
📄
asm_386.s
(42.54 KB)
📄
asm_amd64.h
(631 B)
📄
asm_amd64.s
(60.09 KB)
📄
asm_arm.s
(31.58 KB)
📄
asm_arm64.s
(43.33 KB)
📄
asm_loong64.s
(27.58 KB)
📄
asm_mips64x.s
(24.34 KB)
📄
asm_mipsx.s
(25.82 KB)
📄
asm_ppc64x.h
(1.93 KB)
📄
asm_ppc64x.s
(45.19 KB)
📄
asm_riscv64.s
(26.97 KB)
📄
asm_s390x.s
(27.55 KB)
📄
asm_wasm.s
(11.82 KB)
📄
atomic_arm64.s
(259 B)
📄
atomic_loong64.s
(245 B)
📄
atomic_mips64x.s
(300 B)
📄
atomic_mipsx.s
(262 B)
📄
atomic_pointer.go
(3.66 KB)
📄
atomic_ppc64x.s
(437 B)
📄
atomic_riscv64.s
(275 B)
📄
auxv_none.go
(298 B)
📄
callers_test.go
(12.13 KB)
📁
cgo
📄
cgo.go
(2.5 KB)
📄
cgo_mmap.go
(2.42 KB)
📄
cgo_ppc64x.go
(418 B)
📄
cgo_sigaction.go
(3.28 KB)
📄
cgocall.go
(23.23 KB)
📄
cgocallback.go
(317 B)
📄
cgocheck.go
(7.97 KB)
📄
chan.go
(23.74 KB)
📄
chan_test.go
(23.44 KB)
📄
chanbarrier_test.go
(1.4 KB)
📄
checkptr.go
(3.29 KB)
📄
checkptr_test.go
(2.86 KB)
📄
closure_test.go
(937 B)
📄
compiler.go
(410 B)
📄
complex.go
(1.59 KB)
📄
complex_test.go
(1.05 KB)
📄
conv_wasm_test.go
(2.96 KB)
📄
coro.go
(4.92 KB)
📁
coverage
📄
covercounter.go
(749 B)
📄
covermeta.go
(2.4 KB)
📄
cpuflags.go
(810 B)
📄
cpuflags_amd64.go
(533 B)
📄
cpuflags_arm64.go
(312 B)
📄
cpuprof.go
(7.94 KB)
📄
cputicks.go
(437 B)
📄
crash_cgo_test.go
(23.35 KB)
📄
crash_test.go
(23.12 KB)
📄
crash_unix_test.go
(9.19 KB)
📄
create_file_nounix.go
(305 B)
📄
create_file_unix.go
(368 B)
📁
debug
📄
debug.go
(3.53 KB)
📄
debug_test.go
(7.99 KB)
📄
debugcall.go
(6.75 KB)
📄
debuglog.go
(18.24 KB)
📄
debuglog_off.go
(357 B)
📄
debuglog_on.go
(1.09 KB)
📄
debuglog_test.go
(4.9 KB)
📄
defer_test.go
(11.4 KB)
📄
defs1_linux.go
(845 B)
📄
defs1_netbsd_386.go
(2.91 KB)
📄
defs1_netbsd_amd64.go
(3.14 KB)
📄
defs1_netbsd_arm.go
(3.03 KB)
📄
defs1_netbsd_arm64.go
(3.25 KB)
📄
defs1_solaris_amd64.go
(4.01 KB)
📄
defs2_linux.go
(3.22 KB)
📄
defs3_linux.go
(1.09 KB)
📄
defs_aix.go
(4.17 KB)
📄
defs_aix_ppc64.go
(3.63 KB)
📄
defs_arm_linux.go
(2.67 KB)
📄
defs_darwin.go
(4.18 KB)
📄
defs_darwin_amd64.go
(6.34 KB)
📄
defs_darwin_arm64.go
(4.17 KB)
📄
defs_dragonfly.go
(2.73 KB)
📄
defs_dragonfly_amd64.go
(3.41 KB)
📄
defs_freebsd.go
(3.96 KB)
📄
defs_freebsd_386.go
(4.52 KB)
📄
defs_freebsd_amd64.go
(4.79 KB)
📄
defs_freebsd_arm.go
(3.92 KB)
📄
defs_freebsd_arm64.go
(4.18 KB)
📄
defs_freebsd_riscv64.go
(4.19 KB)
📄
defs_illumos_amd64.go
(285 B)
📄
defs_linux.go
(2.92 KB)
📄
defs_linux_386.go
(4.2 KB)
📄
defs_linux_amd64.go
(4.7 KB)
📄
defs_linux_arm.go
(3.89 KB)
📄
defs_linux_arm64.go
(3.62 KB)
📄
defs_linux_loong64.go
(3.43 KB)
📄
defs_linux_mips64x.go
(3.6 KB)
📄
defs_linux_mipsx.go
(3.6 KB)
📄
defs_linux_ppc64.go
(3.69 KB)
📄
defs_linux_ppc64le.go
(3.69 KB)
📄
defs_linux_riscv64.go
(3.81 KB)
📄
defs_linux_s390x.go
(3.16 KB)
📄
defs_netbsd.go
(2.83 KB)
📄
defs_netbsd_386.go
(855 B)
📄
defs_netbsd_amd64.go
(1.01 KB)
📄
defs_netbsd_arm.go
(764 B)
📄
defs_openbsd.go
(3.06 KB)
📄
defs_openbsd_386.go
(2.91 KB)
📄
defs_openbsd_amd64.go
(3.11 KB)
📄
defs_openbsd_arm.go
(3.03 KB)
📄
defs_openbsd_arm64.go
(2.78 KB)
📄
defs_openbsd_mips64.go
(2.75 KB)
📄
defs_openbsd_ppc64.go
(3 KB)
📄
defs_openbsd_riscv64.go
(2.89 KB)
📄
defs_plan9_386.go
(1.63 KB)
📄
defs_plan9_amd64.go
(1.82 KB)
📄
defs_plan9_arm.go
(1.73 KB)
📄
defs_solaris.go
(3.32 KB)
📄
defs_solaris_amd64.go
(1004 B)
📄
defs_windows.go
(2.25 KB)
📄
defs_windows_386.go
(2.28 KB)
📄
defs_windows_amd64.go
(3.19 KB)
📄
defs_windows_arm.go
(2.57 KB)
📄
defs_windows_arm64.go
(3.07 KB)
📄
duff_386.s
(8.24 KB)
📄
duff_amd64.s
(5.64 KB)
📄
duff_arm.s
(7.11 KB)
📄
duff_arm64.s
(5.27 KB)
📄
duff_loong64.s
(11.9 KB)
📄
duff_mips64x.s
(11.28 KB)
📄
duff_ppc64x.s
(7.06 KB)
📄
duff_riscv64.s
(11.4 KB)
📄
duff_s390x.s
(507 B)
📄
ehooks_test.go
(2.04 KB)
📄
env_plan9.go
(3 KB)
📄
env_posix.go
(1.56 KB)
📄
env_test.go
(1.16 KB)
📄
error.go
(9.29 KB)
📄
example_test.go
(1.55 KB)
📄
exithook.go
(2.32 KB)
📄
export_aix_test.go
(207 B)
📄
export_arm_test.go
(226 B)
📄
export_darwin_test.go
(207 B)
📄
export_debug_amd64_test.go
(3.6 KB)
📄
export_debug_arm64_test.go
(3.49 KB)
📄
export_debug_ppc64le_test.go
(3.5 KB)
📄
export_debug_test.go
(5.07 KB)
📄
export_debuglog_test.go
(1.27 KB)
📄
export_linux_test.go
(378 B)
📄
export_mmap_test.go
(429 B)
📄
export_pipe2_test.go
(310 B)
📄
export_pipe_test.go
(219 B)
📄
export_test.go
(50.52 KB)
📄
export_unix_test.go
(2.27 KB)
📄
export_windows_test.go
(903 B)
📄
extern.go
(18.58 KB)
📄
fastlog2.go
(1.22 KB)
📄
fastlog2_test.go
(784 B)
📄
fastlog2table.go
(904 B)
📄
fds_nonunix.go
(256 B)
📄
fds_test.go
(1.43 KB)
📄
fds_unix.go
(1.27 KB)
📄
float.go
(1.35 KB)
📄
float_test.go
(699 B)
📄
funcdata.h
(2.53 KB)
📄
gc_test.go
(20.32 KB)
📄
gcinfo_test.go
(5.95 KB)
📄
go_tls.h
(366 B)
📄
hash32.go
(1.58 KB)
📄
hash64.go
(1.95 KB)
📄
hash_test.go
(17.24 KB)
📄
heap_test.go
(529 B)
📄
heapdump.go
(17.88 KB)
📄
histogram.go
(7.3 KB)
📄
histogram_test.go
(3.51 KB)
📄
iface.go
(20.92 KB)
📄
iface_test.go
(7.45 KB)
📄
import_test.go
(1.42 KB)
📄
importx_test.go
(763 B)
📁
internal
📄
lfstack.go
(2.03 KB)
📄
lfstack_test.go
(2.74 KB)
📄
libfuzzer.go
(6.34 KB)
📄
libfuzzer_amd64.s
(5.03 KB)
📄
libfuzzer_arm64.s
(3.15 KB)
📄
lock_futex.go
(5.4 KB)
📄
lock_js.go
(7.28 KB)
📄
lock_sema.go
(6.75 KB)
📄
lock_wasip1.go
(2.01 KB)
📄
lockrank.go
(18.19 KB)
📄
lockrank_off.go
(1.17 KB)
📄
lockrank_on.go
(10.27 KB)
📄
lockrank_test.go
(856 B)
📄
malloc.go
(58.5 KB)
📄
malloc_test.go
(10.64 KB)
📄
map.go
(52.17 KB)
📄
map_benchmark_test.go
(10.59 KB)
📄
map_fast32.go
(12.74 KB)
📄
map_fast64.go
(12.92 KB)
📄
map_faststr.go
(14.32 KB)
📄
map_test.go
(31.75 KB)
📄
mbarrier.go
(13.78 KB)
📄
mbitmap.go
(22.54 KB)
📄
mbitmap_allocheaders.go
(44.67 KB)
📄
mbitmap_noallocheaders.go
(28.95 KB)
📄
mcache.go
(10 KB)
📄
mcentral.go
(8.05 KB)
📄
mcheckmark.go
(2.85 KB)
📄
mem.go
(6.72 KB)
📄
mem_aix.go
(2.01 KB)
📄
mem_bsd.go
(2.21 KB)
📄
mem_darwin.go
(1.96 KB)
📄
mem_js.go
(457 B)
📄
mem_linux.go
(4.98 KB)
📄
mem_plan9.go
(447 B)
📄
mem_sbrk.go
(4.19 KB)
📄
mem_wasip1.go
(392 B)
📄
mem_wasm.go
(488 B)
📄
mem_windows.go
(3.88 KB)
📄
memclr_386.s
(2.38 KB)
📄
memclr_amd64.s
(4.91 KB)
📄
memclr_arm.s
(2.6 KB)
📄
memclr_arm64.s
(3.62 KB)
📄
memclr_loong64.s
(843 B)
📄
memclr_mips64x.s
(1.72 KB)
📄
memclr_mipsx.s
(1.32 KB)
📄
memclr_plan9_386.s
(983 B)
📄
memclr_plan9_amd64.s
(511 B)
📄
memclr_ppc64x.s
(4.44 KB)
📄
memclr_riscv64.s
(1.71 KB)
📄
memclr_s390x.s
(1.96 KB)
📄
memclr_wasm.s
(485 B)
📄
memmove_386.s
(4.42 KB)
📄
memmove_amd64.s
(12.48 KB)
📄
memmove_arm.s
(5.9 KB)
📄
memmove_arm64.s
(5.96 KB)
📄
memmove_linux_amd64_test.go
(1.53 KB)
📄
memmove_loong64.s
(1.87 KB)
📄
memmove_mips64x.s
(1.83 KB)
📄
memmove_mipsx.s
(4.4 KB)
📄
memmove_plan9_386.s
(3.06 KB)
📄
memmove_plan9_amd64.s
(3.04 KB)
📄
memmove_ppc64x.s
(4.91 KB)
📄
memmove_riscv64.s
(5.46 KB)
📄
memmove_s390x.s
(2.92 KB)
📄
memmove_test.go
(21.23 KB)
📄
memmove_wasm.s
(479 B)
📁
metrics
📄
metrics.go
(26.01 KB)
📄
metrics_test.go
(42.46 KB)
📄
mfinal.go
(18.91 KB)
📄
mfinal_test.go
(5.57 KB)
📄
mfixalloc.go
(3.13 KB)
📄
mgc.go
(59.29 KB)
📄
mgclimit.go
(17.28 KB)
📄
mgclimit_test.go
(9.02 KB)
📄
mgcmark.go
(53.07 KB)
📄
mgcpacer.go
(55.36 KB)
📄
mgcpacer_test.go
(39.26 KB)
📄
mgcscavenge.go
(52.32 KB)
📄
mgcscavenge_test.go
(25.2 KB)
📄
mgcstack.go
(10.58 KB)
📄
mgcsweep.go
(32.26 KB)
📄
mgcwork.go
(12.89 KB)
📄
mheap.go
(72.64 KB)
📄
minmax.go
(1.46 KB)
📄
minmax_test.go
(3.31 KB)
📄
mkduff.go
(8.04 KB)
📄
mkfastlog2table.go
(3.08 KB)
📄
mklockrank.go
(9 KB)
📄
mkpreempt.go
(15.33 KB)
📄
mksizeclasses.go
(9.52 KB)
📄
mmap.go
(844 B)
📄
mpagealloc.go
(39.23 KB)
📄
mpagealloc_32bit.go
(4.56 KB)
📄
mpagealloc_64bit.go
(9.34 KB)
📄
mpagealloc_test.go
(32.59 KB)
📄
mpagecache.go
(5.59 KB)
📄
mpagecache_test.go
(10.79 KB)
📄
mpallocbits.go
(12.58 KB)
📄
mpallocbits_test.go
(13.69 KB)
📄
mprof.go
(47.4 KB)
📄
mranges.go
(14.46 KB)
📄
mranges_test.go
(5.68 KB)
📁
msan
📄
msan.go
(1.5 KB)
📄
msan0.go
(725 B)
📄
msan_amd64.s
(2.3 KB)
📄
msan_arm64.s
(1.98 KB)
📄
msan_loong64.s
(1.96 KB)
📄
msize_allocheaders.go
(1.32 KB)
📄
msize_noallocheaders.go
(915 B)
📄
mspanset.go
(13.12 KB)
📄
mstats.go
(33.81 KB)
📄
mwbbuf.go
(8.13 KB)
📄
nbpipe_pipe.go
(405 B)
📄
nbpipe_pipe2.go
(344 B)
📄
nbpipe_pipe_test.go
(706 B)
📄
nbpipe_test.go
(1.99 KB)
📄
net_plan9.go
(645 B)
📄
netpoll.go
(20.55 KB)
📄
netpoll_aix.go
(5.06 KB)
📄
netpoll_epoll.go
(4.4 KB)
📄
netpoll_fake.go
(664 B)
📄
netpoll_kqueue.go
(5.62 KB)
📄
netpoll_os_test.go
(520 B)
📄
netpoll_solaris.go
(11.2 KB)
📄
netpoll_stub.go
(1.48 KB)
📄
netpoll_wasip1.go
(6.08 KB)
📄
netpoll_windows.go
(4.01 KB)
📄
nonwindows_stub.go
(729 B)
📄
norace_linux_test.go
(915 B)
📄
norace_test.go
(983 B)
📄
numcpu_freebsd_test.go
(381 B)
📄
os2_aix.go
(20.88 KB)
📄
os2_freebsd.go
(302 B)
📄
os2_openbsd.go
(296 B)
📄
os2_plan9.go
(1.48 KB)
📄
os2_solaris.go
(320 B)
📄
os3_plan9.go
(3.94 KB)
📄
os3_solaris.go
(17.59 KB)
📄
os_aix.go
(8.89 KB)
📄
os_android.go
(463 B)
📄
os_darwin.go
(11.92 KB)
📄
os_darwin_arm64.go
(329 B)
📄
os_dragonfly.go
(7.14 KB)
📄
os_freebsd.go
(11.64 KB)
📄
os_freebsd2.go
(603 B)
📄
os_freebsd_amd64.go
(658 B)
📄
os_freebsd_arm.go
(1.45 KB)
📄
os_freebsd_arm64.go
(320 B)
📄
os_freebsd_noauxv.go
(241 B)
📄
os_freebsd_riscv64.go
(198 B)
📄
os_illumos.go
(3.93 KB)
📄
os_js.go
(767 B)
📄
os_linux.go
(25.71 KB)
📄
os_linux_arm.go
(1.51 KB)
📄
os_linux_arm64.go
(478 B)
📄
os_linux_be64.go
(806 B)
📄
os_linux_generic.go
(870 B)
📄
os_linux_loong64.go
(263 B)
📄
os_linux_mips64x.go
(996 B)
📄
os_linux_mipsx.go
(987 B)
📄
os_linux_noauxv.go
(337 B)
📄
os_linux_novdso.go
(347 B)
📄
os_linux_ppc64x.go
(526 B)
📄
os_linux_riscv64.go
(198 B)
📄
os_linux_s390x.go
(825 B)
📄
os_linux_x86.go
(234 B)
📄
os_netbsd.go
(10.12 KB)
📄
os_netbsd_386.go
(617 B)
📄
os_netbsd_amd64.go
(614 B)
📄
os_netbsd_arm.go
(1.07 KB)
📄
os_netbsd_arm64.go
(769 B)
📄
os_nonopenbsd.go
(437 B)
📄
os_only_solaris.go
(357 B)
📄
os_openbsd.go
(6.23 KB)
📄
os_openbsd_arm.go
(662 B)
📄
os_openbsd_arm64.go
(329 B)
📄
os_openbsd_libc.go
(1.49 KB)
📄
os_openbsd_mips64.go
(329 B)
📄
os_openbsd_syscall.go
(1.36 KB)
📄
os_openbsd_syscall1.go
(441 B)
📄
os_openbsd_syscall2.go
(2.51 KB)
📄
os_plan9.go
(10.18 KB)
📄
os_plan9_arm.go
(375 B)
📄
os_solaris.go
(6.62 KB)
📄
os_unix.go
(436 B)
📄
os_unix_nonlinux.go
(374 B)
📄
os_wasip1.go
(7 KB)
📄
os_wasm.go
(3.15 KB)
📄
os_windows.go
(41.39 KB)
📄
os_windows_arm.go
(511 B)
📄
os_windows_arm64.go
(339 B)
📄
pagetrace_off.go
(550 B)
📄
pagetrace_on.go
(10.36 KB)
📄
panic.go
(41.85 KB)
📄
panic32.go
(4.8 KB)
📄
panic_test.go
(1.71 KB)
📄
panicnil_test.go
(1.25 KB)
📄
pinner.go
(10.98 KB)
📄
pinner_test.go
(11.04 KB)
📄
plugin.go
(4.37 KB)
📁
pprof
📄
preempt.go
(15.03 KB)
📄
preempt_386.s
(824 B)
📄
preempt_amd64.s
(1.67 KB)
📄
preempt_arm.s
(1.49 KB)
📄
preempt_arm64.s
(1.97 KB)
📄
preempt_loong64.s
(2.41 KB)
📄
preempt_mips64x.s
(2.72 KB)
📄
preempt_mipsx.s
(2.68 KB)
📄
preempt_nonwindows.go
(290 B)
📄
preempt_ppc64x.s
(2.72 KB)
📄
preempt_riscv64.s
(2.26 KB)
📄
preempt_s390x.s
(1.01 KB)
📄
preempt_wasm.s
(176 B)
📄
print.go
(5.92 KB)
📄
proc.go
(204.28 KB)
📄
proc_runtime_test.go
(1.38 KB)
📄
proc_test.go
(25.85 KB)
📄
profbuf.go
(18.26 KB)
📄
profbuf_test.go
(8.54 KB)
📄
proflabel.go
(1.52 KB)
📁
race
📄
race.go
(18.81 KB)
📄
race0.go
(2.79 KB)
📄
race_amd64.s
(13.94 KB)
📄
race_arm64.s
(14.21 KB)
📄
race_ppc64le.s
(15.93 KB)
📄
race_s390x.s
(11.99 KB)
📄
rand.go
(7.11 KB)
📄
rand_test.go
(1.95 KB)
📄
rdebug.go
(550 B)
📄
retry.go
(760 B)
📄
rt0_aix_ppc64.s
(4.09 KB)
📄
rt0_android_386.s
(822 B)
📄
rt0_android_amd64.s
(754 B)
📄
rt0_android_arm.s
(843 B)
📄
rt0_android_arm64.s
(941 B)
📄
rt0_darwin_amd64.s
(399 B)
📄
rt0_darwin_arm64.s
(1.69 KB)
📄
rt0_dragonfly_amd64.s
(448 B)
📄
rt0_freebsd_386.s
(454 B)
📄
rt0_freebsd_amd64.s
(442 B)
📄
rt0_freebsd_arm.s
(298 B)
📄
rt0_freebsd_arm64.s
(1.88 KB)
📄
rt0_freebsd_riscv64.s
(2.72 KB)
📄
rt0_illumos_amd64.s
(311 B)
📄
rt0_ios_amd64.s
(425 B)
📄
rt0_ios_arm64.s
(425 B)
📄
rt0_js_wasm.s
(1.53 KB)
📄
rt0_linux_386.s
(450 B)
📄
rt0_linux_amd64.s
(307 B)
📄
rt0_linux_arm.s
(1007 B)
📄
rt0_linux_arm64.s
(1.81 KB)
📄
rt0_linux_loong64.s
(2.01 KB)
📄
rt0_linux_mips64x.s
(1014 B)
📄
rt0_linux_mipsx.s
(797 B)
📄
rt0_linux_ppc64.s
(847 B)
📄
rt0_linux_ppc64le.s
(2.89 KB)
📄
rt0_linux_riscv64.s
(2.65 KB)
📄
rt0_linux_s390x.s
(676 B)
📄
rt0_netbsd_386.s
(452 B)
📄
rt0_netbsd_amd64.s
(309 B)
📄
rt0_netbsd_arm.s
(296 B)
📄
rt0_netbsd_arm64.s
(1.8 KB)
📄
rt0_openbsd_386.s
(454 B)
📄
rt0_openbsd_amd64.s
(311 B)
📄
rt0_openbsd_arm.s
(298 B)
📄
rt0_openbsd_arm64.s
(1.96 KB)
📄
rt0_openbsd_mips64.s
(976 B)
📄
rt0_openbsd_ppc64.s
(370 B)
📄
rt0_openbsd_riscv64.s
(372 B)
📄
rt0_plan9_386.s
(523 B)
📄
rt0_plan9_amd64.s
(481 B)
📄
rt0_plan9_arm.s
(397 B)
📄
rt0_solaris_amd64.s
(311 B)
📄
rt0_wasip1_wasm.s
(387 B)
📄
rt0_windows_386.s
(1.28 KB)
📄
rt0_windows_amd64.s
(1.14 KB)
📄
rt0_windows_arm.s
(386 B)
📄
rt0_windows_arm64.s
(733 B)
📄
runtime-gdb.py
(15.44 KB)
📄
runtime-gdb_test.go
(24.04 KB)
📄
runtime-gdb_unix_test.go
(9.4 KB)
📄
runtime-lldb_test.go
(4.95 KB)
📄
runtime-seh_windows_test.go
(4.7 KB)
📄
runtime.go
(7.1 KB)
📄
runtime1.go
(16.66 KB)
📄
runtime2.go
(46.16 KB)
📄
runtime_boring.go
(606 B)
📄
runtime_linux_test.go
(1.77 KB)
📄
runtime_mmap_test.go
(1.77 KB)
📄
runtime_test.go
(11.81 KB)
📄
runtime_unix_test.go
(1.22 KB)
📄
rwmutex.go
(5 KB)
📄
rwmutex_test.go
(4.21 KB)
📄
security_aix.go
(449 B)
📄
security_issetugid.go
(502 B)
📄
security_linux.go
(335 B)
📄
security_nonunix.go
(256 B)
📄
security_test.go
(4.09 KB)
📄
security_unix.go
(818 B)
📄
select.go
(14.82 KB)
📄
sema.go
(18.43 KB)
📄
sema_test.go
(4.21 KB)
📄
semasleep_test.go
(3.46 KB)
📄
sigaction.go
(489 B)
📄
signal_386.go
(1.72 KB)
📄
signal_aix_ppc64.go
(3.54 KB)
📄
signal_amd64.go
(2.73 KB)
📄
signal_arm.go
(2.54 KB)
📄
signal_arm64.go
(3.83 KB)
📄
signal_darwin.go
(2.13 KB)
📄
signal_darwin_amd64.go
(4 KB)
📄
signal_darwin_arm64.go
(3.6 KB)
📄
signal_dragonfly.go
(2.17 KB)
📄
signal_dragonfly_amd64.go
(2.01 KB)
📄
signal_freebsd.go
(2.2 KB)
📄
signal_freebsd_386.go
(1.55 KB)
📄
signal_freebsd_amd64.go
(2.03 KB)
📄
signal_freebsd_arm.go
(2.18 KB)
📄
signal_freebsd_arm64.go
(3.24 KB)
📄
signal_freebsd_riscv64.go
(3.08 KB)
📄
signal_linux_386.go
(1.59 KB)
📄
signal_linux_amd64.go
(2.05 KB)
📄
signal_linux_arm.go
(2.12 KB)
📄
signal_linux_arm64.go
(2.95 KB)
📄
signal_linux_loong64.go
(3.22 KB)
📄
signal_linux_mips64x.go
(3.35 KB)
📄
signal_linux_mipsx.go
(3.67 KB)
📄
signal_linux_ppc64x.go
(3.5 KB)
📄
signal_linux_riscv64.go
(2.92 KB)
📄
signal_linux_s390x.go
(4.49 KB)
📄
signal_loong64.go
(3.01 KB)
📄
signal_mips64x.go
(3.18 KB)
📄
signal_mipsx.go
(3.06 KB)
📄
signal_netbsd.go
(2.18 KB)
📄
signal_netbsd_386.go
(1.76 KB)
📄
signal_netbsd_amd64.go
(2.33 KB)
📄
signal_netbsd_arm.go
(2.3 KB)
📄
signal_netbsd_arm64.go
(3.4 KB)
📄
signal_openbsd.go
(2.18 KB)
📄
signal_openbsd_386.go
(1.58 KB)
📄
signal_openbsd_amd64.go
(2.04 KB)
📄
signal_openbsd_arm.go
(2.12 KB)
📄
signal_openbsd_arm64.go
(3.39 KB)
📄
signal_openbsd_mips64.go
(3.28 KB)
📄
signal_openbsd_ppc64.go
(3.53 KB)
📄
signal_openbsd_riscv64.go
(3.12 KB)
📄
signal_plan9.go
(1.93 KB)
📄
signal_ppc64x.go
(3.71 KB)
📄
signal_riscv64.go
(2.91 KB)
📄
signal_solaris.go
(4.5 KB)
📄
signal_solaris_amd64.go
(2.47 KB)
📄
signal_unix.go
(44.11 KB)
📄
signal_windows.go
(14.48 KB)
📄
signal_windows_test.go
(8.98 KB)
📄
sigqueue.go
(7.62 KB)
📄
sigqueue_note.go
(648 B)
📄
sigqueue_plan9.go
(3.25 KB)
📄
sigtab_aix.go
(11.3 KB)
📄
sigtab_linux_generic.go
(3.52 KB)
📄
sigtab_linux_mipsx.go
(5.95 KB)
📄
sizeclasses.go
(9.17 KB)
📄
sizeof_test.go
(1003 B)
📄
slice.go
(11.23 KB)
📄
slice_test.go
(10.32 KB)
📄
softfloat64.go
(11.54 KB)
📄
softfloat64_test.go
(4.04 KB)
📄
stack.go
(40.02 KB)
📄
stack_test.go
(23.14 KB)
📄
start_line_amd64_test.go
(647 B)
📄
start_line_test.go
(2.58 KB)
📄
stkframe.go
(9.88 KB)
📄
string.go
(13.35 KB)
📄
string_test.go
(13.33 KB)
📄
stubs.go
(17.39 KB)
📄
stubs2.go
(1.15 KB)
📄
stubs3.go
(324 B)
📄
stubs_386.go
(708 B)
📄
stubs_amd64.go
(1.38 KB)
📄
stubs_arm.go
(689 B)
📄
stubs_arm64.go
(700 B)
📄
stubs_linux.go
(650 B)
📄
stubs_loong64.go
(638 B)
📄
stubs_mips64x.go
(522 B)
📄
stubs_mipsx.go
(441 B)
📄
stubs_nonlinux.go
(298 B)
📄
stubs_ppc64.go
(302 B)
📄
stubs_ppc64x.go
(688 B)
📄
stubs_riscv64.go
(695 B)
📄
stubs_s390x.go
(414 B)
📄
symtab.go
(34.76 KB)
📄
symtab_test.go
(7.48 KB)
📄
symtabinl.go
(3.81 KB)
📄
symtabinl_test.go
(2.97 KB)
📄
sys_aix_ppc64.s
(7.42 KB)
📄
sys_arm.go
(521 B)
📄
sys_arm64.go
(469 B)
📄
sys_darwin.go
(22.56 KB)
📄
sys_darwin_amd64.s
(19.65 KB)
📄
sys_darwin_arm64.go
(1.74 KB)
📄
sys_darwin_arm64.s
(18.28 KB)
📄
sys_dragonfly_amd64.s
(8.31 KB)
📄
sys_freebsd_386.s
(9.41 KB)
📄
sys_freebsd_amd64.s
(12.67 KB)
📄
sys_freebsd_arm.s
(10.38 KB)
📄
sys_freebsd_arm64.s
(9.49 KB)
📄
sys_freebsd_riscv64.s
(8.92 KB)
📄
sys_libc.go
(1.84 KB)
📄
sys_linux_386.s
(17.89 KB)
📄
sys_linux_amd64.s
(15.74 KB)
📄
sys_linux_arm.s
(13.5 KB)
📄
sys_linux_arm64.s
(16.71 KB)
📄
sys_linux_loong64.s
(14.16 KB)
📄
sys_linux_mips64x.s
(11.96 KB)
📄
sys_linux_mipsx.s
(9.69 KB)
📄
sys_linux_ppc64x.s
(18.09 KB)
📄
sys_linux_riscv64.s
(11.48 KB)
📄
sys_linux_s390x.s
(12.49 KB)
📄
sys_loong64.go
(489 B)
📄
sys_mips64x.go
(500 B)
📄
sys_mipsx.go
(496 B)
📄
sys_netbsd_386.s
(9.61 KB)
📄
sys_netbsd_amd64.s
(9.78 KB)
📄
sys_netbsd_arm.s
(10.58 KB)
📄
sys_netbsd_arm64.s
(9.47 KB)
📄
sys_nonppc64x.go
(245 B)
📄
sys_openbsd.go
(2.59 KB)
📄
sys_openbsd1.go
(1.23 KB)
📄
sys_openbsd2.go
(8.67 KB)
📄
sys_openbsd3.go
(3.37 KB)
📄
sys_openbsd_386.s
(20.4 KB)
📄
sys_openbsd_amd64.s
(15.54 KB)
📄
sys_openbsd_arm.s
(18.46 KB)
📄
sys_openbsd_arm64.s
(15.05 KB)
📄
sys_openbsd_mips64.s
(8.81 KB)
📄
sys_openbsd_ppc64.s
(15.3 KB)
📄
sys_openbsd_riscv64.s
(16.8 KB)
📄
sys_plan9_386.s
(4.48 KB)
📄
sys_plan9_amd64.s
(4.56 KB)
📄
sys_plan9_arm.s
(7.03 KB)
📄
sys_ppc64x.go
(532 B)
📄
sys_riscv64.go
(469 B)
📄
sys_s390x.go
(469 B)
📄
sys_solaris_amd64.s
(6.42 KB)
📄
sys_wasm.go
(758 B)
📄
sys_wasm.s
(1.43 KB)
📄
sys_windows_386.s
(6.46 KB)
📄
sys_windows_amd64.s
(8.41 KB)
📄
sys_windows_arm.s
(7.72 KB)
📄
sys_windows_arm64.s
(6.8 KB)
📄
sys_x86.go
(552 B)
📄
syscall2_solaris.go
(1.85 KB)
📄
syscall_aix.go
(6.33 KB)
📄
syscall_solaris.go
(8.38 KB)
📄
syscall_unix_test.go
(635 B)
📄
syscall_windows.go
(16.57 KB)
📄
syscall_windows_test.go
(32.45 KB)
📄
tagptr.go
(496 B)
📄
tagptr_32bit.go
(927 B)
📄
tagptr_64bit.go
(3.23 KB)
📄
test_amd64.go
(196 B)
📄
test_amd64.s
(316 B)
📄
test_stubs.go
(218 B)
📁
testdata
📄
textflag.h
(1.47 KB)
📄
time.go
(30.57 KB)
📄
time_fake.go
(2.5 KB)
📄
time_linux_amd64.s
(2.02 KB)
📄
time_nofake.go
(709 B)
📄
time_test.go
(2.04 KB)
📄
time_windows.h
(753 B)
📄
time_windows_386.s
(1.71 KB)
📄
time_windows_amd64.s
(786 B)
📄
time_windows_arm.s
(1.97 KB)
📄
time_windows_arm64.s
(906 B)
📄
timeasm.go
(418 B)
📄
timestub.go
(532 B)
📄
timestub2.go
(363 B)
📄
tls_arm.s
(3.45 KB)
📄
tls_arm64.h
(1.1 KB)
📄
tls_arm64.s
(1.2 KB)
📄
tls_loong64.s
(589 B)
📄
tls_mips64x.s
(733 B)
📄
tls_mipsx.s
(710 B)
📄
tls_ppc64x.s
(1.52 KB)
📄
tls_riscv64.s
(615 B)
📄
tls_s390x.s
(1.55 KB)
📄
tls_stub.go
(260 B)
📄
tls_windows_amd64.go
(294 B)
📁
trace
📄
trace.go
(62.76 KB)
📄
trace2.go
(33.81 KB)
📄
trace2buf.go
(6.58 KB)
📄
trace2cpu.go
(8.87 KB)
📄
trace2event.go
(8.39 KB)
📄
trace2map.go
(4.36 KB)
📄
trace2region.go
(1.68 KB)
📄
trace2runtime.go
(24.2 KB)
📄
trace2stack.go
(9.45 KB)
📄
trace2status.go
(7.24 KB)
📄
trace2string.go
(2.59 KB)
📄
trace2time.go
(3.21 KB)
📄
trace_cgo_test.go
(4.47 KB)
📄
traceback.go
(54.61 KB)
📄
traceback_test.go
(22.95 KB)
📄
tracebackx_test.go
(509 B)
📄
type.go
(12.1 KB)
📄
typekind.go
(743 B)
📄
unsafe.go
(2.97 KB)
📄
unsafepoint_test.go
(3.27 KB)
📄
utf8.go
(3.39 KB)
📄
vdso_elf32.go
(2.76 KB)
📄
vdso_elf64.go
(2.84 KB)
📄
vdso_freebsd.go
(2.44 KB)
📄
vdso_freebsd_arm.go
(454 B)
📄
vdso_freebsd_arm64.go
(454 B)
📄
vdso_freebsd_riscv64.go
(429 B)
📄
vdso_freebsd_x86.go
(1.86 KB)
📄
vdso_in_none.go
(443 B)
📄
vdso_linux.go
(7.77 KB)
📄
vdso_linux_386.go
(669 B)
📄
vdso_linux_amd64.go
(685 B)
📄
vdso_linux_arm.go
(669 B)
📄
vdso_linux_arm64.go
(670 B)
📄
vdso_linux_loong64.go
(793 B)
📄
vdso_linux_mips64x.go
(850 B)
📄
vdso_linux_ppc64x.go
(672 B)
📄
vdso_linux_riscv64.go
(666 B)
📄
vdso_linux_s390x.go
(659 B)
📄
vdso_test.go
(3.71 KB)
📄
vlop_386.s
(2.02 KB)
📄
vlop_arm.s
(7.06 KB)
📄
vlop_arm_test.go
(3.75 KB)
📄
vlrt.go
(6.71 KB)
📄
wincallback.go
(3.45 KB)
📄
write_err.go
(291 B)
📄
write_err_android.go
(4.65 KB)
📄
zcallback_windows.go
(155 B)
📄
zcallback_windows.s
(63.06 KB)
📄
zcallback_windows_arm.s
(89.32 KB)
📄
zcallback_windows_arm64.s
(89.32 KB)
Editing: panic.go
// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package runtime import ( "internal/abi" "internal/goarch" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" ) // throwType indicates the current type of ongoing throw, which affects the // amount of detail printed to stderr. Higher values include more detail. type throwType uint32 const ( // throwTypeNone means that we are not throwing. throwTypeNone throwType = iota // throwTypeUser is a throw due to a problem with the application. // // These throws do not include runtime frames, system goroutines, or // frame metadata. throwTypeUser // throwTypeRuntime is a throw due to a problem with Go itself. // // These throws include as much information as possible to aid in // debugging the runtime, including runtime frames, system goroutines, // and frame metadata. throwTypeRuntime ) // We have two different ways of doing defers. The older way involves creating a // defer record at the time that a defer statement is executing and adding it to a // defer chain. This chain is inspected by the deferreturn call at all function // exits in order to run the appropriate defer calls. A cheaper way (which we call // open-coded defers) is used for functions in which no defer statements occur in // loops. In that case, we simply store the defer function/arg information into // specific stack slots at the point of each defer statement, as well as setting a // bit in a bitmask. At each function exit, we add inline code to directly make // the appropriate defer calls based on the bitmask and fn/arg information stored // on the stack. During panic/Goexit processing, the appropriate defer calls are // made using extra funcdata info that indicates the exact stack slots that // contain the bitmask and defer fn/args. // Check to make sure we can really generate a panic. If the panic // was generated from the runtime, or from inside malloc, then convert // to a throw of msg. // pc should be the program counter of the compiler-generated code that // triggered this panic. func panicCheck1(pc uintptr, msg string) { if goarch.IsWasm == 0 && hasPrefix(funcname(findfunc(pc)), "runtime.") { // Note: wasm can't tail call, so we can't get the original caller's pc. throw(msg) } // TODO: is this redundant? How could we be in malloc // but not in the runtime? runtime/internal/*, maybe? gp := getg() if gp != nil && gp.m != nil && gp.m.mallocing != 0 { throw(msg) } } // Same as above, but calling from the runtime is allowed. // // Using this function is necessary for any panic that may be // generated by runtime.sigpanic, since those are always called by the // runtime. func panicCheck2(err string) { // panic allocates, so to avoid recursive malloc, turn panics // during malloc into throws. gp := getg() if gp != nil && gp.m != nil && gp.m.mallocing != 0 { throw(err) } } // Many of the following panic entry-points turn into throws when they // happen in various runtime contexts. These should never happen in // the runtime, and if they do, they indicate a serious issue and // should not be caught by user code. // // The panic{Index,Slice,divide,shift} functions are called by // code generated by the compiler for out of bounds index expressions, // out of bounds slice expressions, division by zero, and shift by negative. // The panicdivide (again), panicoverflow, panicfloat, and panicmem // functions are called by the signal handler when a signal occurs // indicating the respective problem. // // Since panic{Index,Slice,shift} are never called directly, and // since the runtime package should never have an out of bounds slice // or array reference or negative shift, if we see those functions called from the // runtime package we turn the panic into a throw. That will dump the // entire runtime stack for easier debugging. // // The entry points called by the signal handler will be called from // runtime.sigpanic, so we can't disallow calls from the runtime to // these (they always look like they're called from the runtime). // Hence, for these, we just check for clearly bad runtime conditions. // // The panic{Index,Slice} functions are implemented in assembly and tail call // to the goPanic{Index,Slice} functions below. This is done so we can use // a space-minimal register calling convention. // failures in the comparisons for s[x], 0 <= x < y (y == len(s)) // //go:yeswritebarrierrec func goPanicIndex(x int, y int) { panicCheck1(getcallerpc(), "index out of range") panic(boundsError{x: int64(x), signed: true, y: y, code: boundsIndex}) } //go:yeswritebarrierrec func goPanicIndexU(x uint, y int) { panicCheck1(getcallerpc(), "index out of range") panic(boundsError{x: int64(x), signed: false, y: y, code: boundsIndex}) } // failures in the comparisons for s[:x], 0 <= x <= y (y == len(s) or cap(s)) // //go:yeswritebarrierrec func goPanicSliceAlen(x int, y int) { panicCheck1(getcallerpc(), "slice bounds out of range") panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceAlen}) } //go:yeswritebarrierrec func goPanicSliceAlenU(x uint, y int) { panicCheck1(getcallerpc(), "slice bounds out of range") panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceAlen}) } //go:yeswritebarrierrec func goPanicSliceAcap(x int, y int) { panicCheck1(getcallerpc(), "slice bounds out of range") panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceAcap}) } //go:yeswritebarrierrec func goPanicSliceAcapU(x uint, y int) { panicCheck1(getcallerpc(), "slice bounds out of range") panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceAcap}) } // failures in the comparisons for s[x:y], 0 <= x <= y // //go:yeswritebarrierrec func goPanicSliceB(x int, y int) { panicCheck1(getcallerpc(), "slice bounds out of range") panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceB}) } //go:yeswritebarrierrec func goPanicSliceBU(x uint, y int) { panicCheck1(getcallerpc(), "slice bounds out of range") panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceB}) } // failures in the comparisons for s[::x], 0 <= x <= y (y == len(s) or cap(s)) func goPanicSlice3Alen(x int, y int) { panicCheck1(getcallerpc(), "slice bounds out of range") panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3Alen}) } func goPanicSlice3AlenU(x uint, y int) { panicCheck1(getcallerpc(), "slice bounds out of range") panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3Alen}) } func goPanicSlice3Acap(x int, y int) { panicCheck1(getcallerpc(), "slice bounds out of range") panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3Acap}) } func goPanicSlice3AcapU(x uint, y int) { panicCheck1(getcallerpc(), "slice bounds out of range") panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3Acap}) } // failures in the comparisons for s[:x:y], 0 <= x <= y func goPanicSlice3B(x int, y int) { panicCheck1(getcallerpc(), "slice bounds out of range") panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3B}) } func goPanicSlice3BU(x uint, y int) { panicCheck1(getcallerpc(), "slice bounds out of range") panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3B}) } // failures in the comparisons for s[x:y:], 0 <= x <= y func goPanicSlice3C(x int, y int) { panicCheck1(getcallerpc(), "slice bounds out of range") panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3C}) } func goPanicSlice3CU(x uint, y int) { panicCheck1(getcallerpc(), "slice bounds out of range") panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3C}) } // failures in the conversion ([x]T)(s) or (*[x]T)(s), 0 <= x <= y, y == len(s) func goPanicSliceConvert(x int, y int) { panicCheck1(getcallerpc(), "slice length too short to convert to array or pointer to array") panic(boundsError{x: int64(x), signed: true, y: y, code: boundsConvert}) } // Implemented in assembly, as they take arguments in registers. // Declared here to mark them as ABIInternal. func panicIndex(x int, y int) func panicIndexU(x uint, y int) func panicSliceAlen(x int, y int) func panicSliceAlenU(x uint, y int) func panicSliceAcap(x int, y int) func panicSliceAcapU(x uint, y int) func panicSliceB(x int, y int) func panicSliceBU(x uint, y int) func panicSlice3Alen(x int, y int) func panicSlice3AlenU(x uint, y int) func panicSlice3Acap(x int, y int) func panicSlice3AcapU(x uint, y int) func panicSlice3B(x int, y int) func panicSlice3BU(x uint, y int) func panicSlice3C(x int, y int) func panicSlice3CU(x uint, y int) func panicSliceConvert(x int, y int) var shiftError = error(errorString("negative shift amount")) //go:yeswritebarrierrec func panicshift() { panicCheck1(getcallerpc(), "negative shift amount") panic(shiftError) } var divideError = error(errorString("integer divide by zero")) //go:yeswritebarrierrec func panicdivide() { panicCheck2("integer divide by zero") panic(divideError) } var overflowError = error(errorString("integer overflow")) func panicoverflow() { panicCheck2("integer overflow") panic(overflowError) } var floatError = error(errorString("floating point error")) func panicfloat() { panicCheck2("floating point error") panic(floatError) } var memoryError = error(errorString("invalid memory address or nil pointer dereference")) func panicmem() { panicCheck2("invalid memory address or nil pointer dereference") panic(memoryError) } func panicmemAddr(addr uintptr) { panicCheck2("invalid memory address or nil pointer dereference") panic(errorAddressString{msg: "invalid memory address or nil pointer dereference", addr: addr}) } // Create a new deferred function fn, which has no arguments and results. // The compiler turns a defer statement into a call to this. func deferproc(fn func()) { gp := getg() if gp.m.curg != gp { // go code on the system stack can't defer throw("defer on system stack") } d := newdefer() d.link = gp._defer gp._defer = d d.fn = fn d.pc = getcallerpc() // We must not be preempted between calling getcallersp and // storing it to d.sp because getcallersp's result is a // uintptr stack pointer. d.sp = getcallersp() // deferproc returns 0 normally. // a deferred func that stops a panic // makes the deferproc return 1. // the code the compiler generates always // checks the return value and jumps to the // end of the function if deferproc returns != 0. return0() // No code can go here - the C return register has // been set and must not be clobbered. } var rangeExitError = error(errorString("range function continued iteration after exit")) //go:noinline func panicrangeexit() { panic(rangeExitError) } // deferrangefunc is called by functions that are about to // execute a range-over-function loop in which the loop body // may execute a defer statement. That defer needs to add to // the chain for the current function, not the func literal synthesized // to represent the loop body. To do that, the original function // calls deferrangefunc to obtain an opaque token representing // the current frame, and then the loop body uses deferprocat // instead of deferproc to add to that frame's defer lists. // // The token is an 'any' with underlying type *atomic.Pointer[_defer]. // It is the atomically-updated head of a linked list of _defer structs // representing deferred calls. At the same time, we create a _defer // struct on the main g._defer list with d.head set to this head pointer. // // The g._defer list is now a linked list of deferred calls, // but an atomic list hanging off: // // g._defer => d4 -> d3 -> drangefunc -> d2 -> d1 -> nil // | .head // | // +--> dY -> dX -> nil // // with each -> indicating a d.link pointer, and where drangefunc // has the d.rangefunc = true bit set. // Note that the function being ranged over may have added // its own defers (d4 and d3), so drangefunc need not be at the // top of the list when deferprocat is used. This is why we pass // the atomic head explicitly. // // To keep misbehaving programs from crashing the runtime, // deferprocat pushes new defers onto the .head list atomically. // The fact that it is a separate list from the main goroutine // defer list means that the main goroutine's defers can still // be handled non-atomically. // // In the diagram, dY and dX are meant to be processed when // drangefunc would be processed, which is to say the defer order // should be d4, d3, dY, dX, d2, d1. To make that happen, // when defer processing reaches a d with rangefunc=true, // it calls deferconvert to atomically take the extras // away from d.head and then adds them to the main list. // // That is, deferconvert changes this list: // // g._defer => drangefunc -> d2 -> d1 -> nil // | .head // | // +--> dY -> dX -> nil // // into this list: // // g._defer => dY -> dX -> d2 -> d1 -> nil // // It also poisons *drangefunc.head so that any future // deferprocat using that head will throw. // (The atomic head is ordinary garbage collected memory so that // it's not a problem if user code holds onto it beyond // the lifetime of drangefunc.) // // TODO: We could arrange for the compiler to call into the // runtime after the loop finishes normally, to do an eager // deferconvert, which would catch calling the loop body // and having it defer after the loop is done. If we have a // more general catch of loop body misuse, though, this // might not be worth worrying about in addition. // // See also ../cmd/compile/internal/rangefunc/rewrite.go. func deferrangefunc() any { gp := getg() if gp.m.curg != gp { // go code on the system stack can't defer throw("defer on system stack") } d := newdefer() d.link = gp._defer gp._defer = d d.pc = getcallerpc() // We must not be preempted between calling getcallersp and // storing it to d.sp because getcallersp's result is a // uintptr stack pointer. d.sp = getcallersp() d.rangefunc = true d.head = new(atomic.Pointer[_defer]) return d.head } // badDefer returns a fixed bad defer pointer for poisoning an atomic defer list head. func badDefer() *_defer { return (*_defer)(unsafe.Pointer(uintptr(1))) } // deferprocat is like deferproc but adds to the atomic list represented by frame. // See the doc comment for deferrangefunc for details. func deferprocat(fn func(), frame any) { head := frame.(*atomic.Pointer[_defer]) if raceenabled { racewritepc(unsafe.Pointer(head), getcallerpc(), abi.FuncPCABIInternal(deferprocat)) } d1 := newdefer() d1.fn = fn for { d1.link = head.Load() if d1.link == badDefer() { throw("defer after range func returned") } if head.CompareAndSwap(d1.link, d1) { break } } // Must be last - see deferproc above. return0() } // deferconvert converts a rangefunc defer list into an ordinary list. // See the doc comment for deferrangefunc for details. func deferconvert(d *_defer) *_defer { head := d.head if raceenabled { racereadpc(unsafe.Pointer(head), getcallerpc(), abi.FuncPCABIInternal(deferconvert)) } tail := d.link d.rangefunc = false d0 := d for { d = head.Load() if head.CompareAndSwap(d, badDefer()) { break } } if d == nil { freedefer(d0) return tail } for d1 := d; ; d1 = d1.link { d1.sp = d0.sp d1.pc = d0.pc if d1.link == nil { d1.link = tail break } } freedefer(d0) return d } // deferprocStack queues a new deferred function with a defer record on the stack. // The defer record must have its fn field initialized. // All other fields can contain junk. // Nosplit because of the uninitialized pointer fields on the stack. // //go:nosplit func deferprocStack(d *_defer) { gp := getg() if gp.m.curg != gp { // go code on the system stack can't defer throw("defer on system stack") } // fn is already set. // The other fields are junk on entry to deferprocStack and // are initialized here. d.heap = false d.rangefunc = false d.sp = getcallersp() d.pc = getcallerpc() // The lines below implement: // d.panic = nil // d.fd = nil // d.link = gp._defer // d.head = nil // gp._defer = d // But without write barriers. The first three are writes to // the stack so they don't need a write barrier, and furthermore // are to uninitialized memory, so they must not use a write barrier. // The fourth write does not require a write barrier because we // explicitly mark all the defer structures, so we don't need to // keep track of pointers to them with a write barrier. *(*uintptr)(unsafe.Pointer(&d.link)) = uintptr(unsafe.Pointer(gp._defer)) *(*uintptr)(unsafe.Pointer(&d.head)) = 0 *(*uintptr)(unsafe.Pointer(&gp._defer)) = uintptr(unsafe.Pointer(d)) return0() // No code can go here - the C return register has // been set and must not be clobbered. } // Each P holds a pool for defers. // Allocate a Defer, usually using per-P pool. // Each defer must be released with freedefer. The defer is not // added to any defer chain yet. func newdefer() *_defer { var d *_defer mp := acquirem() pp := mp.p.ptr() if len(pp.deferpool) == 0 && sched.deferpool != nil { lock(&sched.deferlock) for len(pp.deferpool) < cap(pp.deferpool)/2 && sched.deferpool != nil { d := sched.deferpool sched.deferpool = d.link d.link = nil pp.deferpool = append(pp.deferpool, d) } unlock(&sched.deferlock) } if n := len(pp.deferpool); n > 0 { d = pp.deferpool[n-1] pp.deferpool[n-1] = nil pp.deferpool = pp.deferpool[:n-1] } releasem(mp) mp, pp = nil, nil if d == nil { // Allocate new defer. d = new(_defer) } d.heap = true return d } // Free the given defer. // The defer cannot be used after this call. // // This is nosplit because the incoming defer is in a perilous state. // It's not on any defer list, so stack copying won't adjust stack // pointers in it (namely, d.link). Hence, if we were to copy the // stack, d could then contain a stale pointer. // //go:nosplit func freedefer(d *_defer) { d.link = nil // After this point we can copy the stack. if d.fn != nil { freedeferfn() } if !d.heap { return } mp := acquirem() pp := mp.p.ptr() if len(pp.deferpool) == cap(pp.deferpool) { // Transfer half of local cache to the central cache. var first, last *_defer for len(pp.deferpool) > cap(pp.deferpool)/2 { n := len(pp.deferpool) d := pp.deferpool[n-1] pp.deferpool[n-1] = nil pp.deferpool = pp.deferpool[:n-1] if first == nil { first = d } else { last.link = d } last = d } lock(&sched.deferlock) last.link = sched.deferpool sched.deferpool = first unlock(&sched.deferlock) } *d = _defer{} pp.deferpool = append(pp.deferpool, d) releasem(mp) mp, pp = nil, nil } // Separate function so that it can split stack. // Windows otherwise runs out of stack space. func freedeferfn() { // fn must be cleared before d is unlinked from gp. throw("freedefer with d.fn != nil") } // deferreturn runs deferred functions for the caller's frame. // The compiler inserts a call to this at the end of any // function which calls defer. func deferreturn() { var p _panic p.deferreturn = true p.start(getcallerpc(), unsafe.Pointer(getcallersp())) for { fn, ok := p.nextDefer() if !ok { break } fn() } } // Goexit terminates the goroutine that calls it. No other goroutine is affected. // Goexit runs all deferred calls before terminating the goroutine. Because Goexit // is not a panic, any recover calls in those deferred functions will return nil. // // Calling Goexit from the main goroutine terminates that goroutine // without func main returning. Since func main has not returned, // the program continues execution of other goroutines. // If all other goroutines exit, the program crashes. func Goexit() { // Create a panic object for Goexit, so we can recognize when it might be // bypassed by a recover(). var p _panic p.goexit = true p.start(getcallerpc(), unsafe.Pointer(getcallersp())) for { fn, ok := p.nextDefer() if !ok { break } fn() } goexit1() } // Call all Error and String methods before freezing the world. // Used when crashing with panicking. func preprintpanics(p *_panic) { defer func() { text := "panic while printing panic value" switch r := recover().(type) { case nil: // nothing to do case string: throw(text + ": " + r) default: throw(text + ": type " + toRType(efaceOf(&r)._type).string()) } }() for p != nil { switch v := p.arg.(type) { case error: p.arg = v.Error() case stringer: p.arg = v.String() } p = p.link } } // Print all currently active panics. Used when crashing. // Should only be called after preprintpanics. func printpanics(p *_panic) { if p.link != nil { printpanics(p.link) if !p.link.goexit { print("\t") } } if p.goexit { return } print("panic: ") printany(p.arg) if p.recovered { print(" [recovered]") } print("\n") } // readvarintUnsafe reads the uint32 in varint format starting at fd, and returns the // uint32 and a pointer to the byte following the varint. // // The implementation is the same with runtime.readvarint, except that this function // uses unsafe.Pointer for speed. func readvarintUnsafe(fd unsafe.Pointer) (uint32, unsafe.Pointer) { var r uint32 var shift int for { b := *(*uint8)(fd) fd = add(fd, unsafe.Sizeof(b)) if b < 128 { return r + uint32(b)<<shift, fd } r += uint32(b&0x7F) << (shift & 31) shift += 7 if shift > 28 { panic("Bad varint") } } } // A PanicNilError happens when code calls panic(nil). // // Before Go 1.21, programs that called panic(nil) observed recover returning nil. // Starting in Go 1.21, programs that call panic(nil) observe recover returning a *PanicNilError. // Programs can change back to the old behavior by setting GODEBUG=panicnil=1. type PanicNilError struct { // This field makes PanicNilError structurally different from // any other struct in this package, and the _ makes it different // from any struct in other packages too. // This avoids any accidental conversions being possible // between this struct and some other struct sharing the same fields, // like happened in go.dev/issue/56603. _ [0]*PanicNilError } func (*PanicNilError) Error() string { return "panic called with nil argument" } func (*PanicNilError) RuntimeError() {} var panicnil = &godebugInc{name: "panicnil"} // The implementation of the predeclared function panic. func gopanic(e any) { if e == nil { if debug.panicnil.Load() != 1 { e = new(PanicNilError) } else { panicnil.IncNonDefault() } } gp := getg() if gp.m.curg != gp { print("panic: ") printany(e) print("\n") throw("panic on system stack") } if gp.m.mallocing != 0 { print("panic: ") printany(e) print("\n") throw("panic during malloc") } if gp.m.preemptoff != "" { print("panic: ") printany(e) print("\n") print("preempt off reason: ") print(gp.m.preemptoff) print("\n") throw("panic during preemptoff") } if gp.m.locks != 0 { print("panic: ") printany(e) print("\n") throw("panic holding locks") } var p _panic p.arg = e runningPanicDefers.Add(1) p.start(getcallerpc(), unsafe.Pointer(getcallersp())) for { fn, ok := p.nextDefer() if !ok { break } fn() } // ran out of deferred calls - old-school panic now // Because it is unsafe to call arbitrary user code after freezing // the world, we call preprintpanics to invoke all necessary Error // and String methods to prepare the panic strings before startpanic. preprintpanics(&p) fatalpanic(&p) // should not return *(*int)(nil) = 0 // not reached } // start initializes a panic to start unwinding the stack. // // If p.goexit is true, then start may return multiple times. func (p *_panic) start(pc uintptr, sp unsafe.Pointer) { gp := getg() // Record the caller's PC and SP, so recovery can identify panics // that have been recovered. Also, so that if p is from Goexit, we // can restart its defer processing loop if a recovered panic tries // to jump past it. p.startPC = getcallerpc() p.startSP = unsafe.Pointer(getcallersp()) if p.deferreturn { p.sp = sp if s := (*savedOpenDeferState)(gp.param); s != nil { // recovery saved some state for us, so that we can resume // calling open-coded defers without unwinding the stack. gp.param = nil p.retpc = s.retpc p.deferBitsPtr = (*byte)(add(sp, s.deferBitsOffset)) p.slotsPtr = add(sp, s.slotsOffset) } return } p.link = gp._panic gp._panic = (*_panic)(noescape(unsafe.Pointer(p))) // Initialize state machine, and find the first frame with a defer. // // Note: We could use startPC and startSP here, but callers will // never have defer statements themselves. By starting at their // caller instead, we avoid needing to unwind through an extra // frame. It also somewhat simplifies the terminating condition for // deferreturn. p.lr, p.fp = pc, sp p.nextFrame() } // nextDefer returns the next deferred function to invoke, if any. // // Note: The "ok bool" result is necessary to correctly handle when // the deferred function itself was nil (e.g., "defer (func())(nil)"). func (p *_panic) nextDefer() (func(), bool) { gp := getg() if !p.deferreturn { if gp._panic != p { throw("bad panic stack") } if p.recovered { mcall(recovery) // does not return throw("recovery failed") } } // The assembler adjusts p.argp in wrapper functions that shouldn't // be visible to recover(), so we need to restore it each iteration. p.argp = add(p.startSP, sys.MinFrameSize) for { for p.deferBitsPtr != nil { bits := *p.deferBitsPtr // Check whether any open-coded defers are still pending. // // Note: We need to check this upfront (rather than after // clearing the top bit) because it's possible that Goexit // invokes a deferred call, and there were still more pending // open-coded defers in the frame; but then the deferred call // panic and invoked the remaining defers in the frame, before // recovering and restarting the Goexit loop. if bits == 0 { p.deferBitsPtr = nil break } // Find index of top bit set. i := 7 - uintptr(sys.LeadingZeros8(bits)) // Clear bit and store it back. bits &^= 1 << i *p.deferBitsPtr = bits return *(*func())(add(p.slotsPtr, i*goarch.PtrSize)), true } Recheck: if d := gp._defer; d != nil && d.sp == uintptr(p.sp) { if d.rangefunc { gp._defer = deferconvert(d) goto Recheck } fn := d.fn d.fn = nil // TODO(mdempsky): Instead of having each deferproc call have // its own "deferreturn(); return" sequence, we should just make // them reuse the one we emit for open-coded defers. p.retpc = d.pc // Unlink and free. gp._defer = d.link freedefer(d) return fn, true } if !p.nextFrame() { return nil, false } } } // nextFrame finds the next frame that contains deferred calls, if any. func (p *_panic) nextFrame() (ok bool) { if p.lr == 0 { return false } gp := getg() systemstack(func() { var limit uintptr if d := gp._defer; d != nil { limit = d.sp } var u unwinder u.initAt(p.lr, uintptr(p.fp), 0, gp, 0) for { if !u.valid() { p.lr = 0 return // ok == false } // TODO(mdempsky): If we populate u.frame.fn.deferreturn for // every frame containing a defer (not just open-coded defers), // then we can simply loop until we find the next frame where // it's non-zero. if u.frame.sp == limit { break // found a frame with linked defers } if p.initOpenCodedDefers(u.frame.fn, unsafe.Pointer(u.frame.varp)) { break // found a frame with open-coded defers } u.next() } p.lr = u.frame.lr p.sp = unsafe.Pointer(u.frame.sp) p.fp = unsafe.Pointer(u.frame.fp) ok = true }) return } func (p *_panic) initOpenCodedDefers(fn funcInfo, varp unsafe.Pointer) bool { fd := funcdata(fn, abi.FUNCDATA_OpenCodedDeferInfo) if fd == nil { return false } if fn.deferreturn == 0 { throw("missing deferreturn") } deferBitsOffset, fd := readvarintUnsafe(fd) deferBitsPtr := (*uint8)(add(varp, -uintptr(deferBitsOffset))) if *deferBitsPtr == 0 { return false // has open-coded defers, but none pending } slotsOffset, fd := readvarintUnsafe(fd) p.retpc = fn.entry() + uintptr(fn.deferreturn) p.deferBitsPtr = deferBitsPtr p.slotsPtr = add(varp, -uintptr(slotsOffset)) return true } // The implementation of the predeclared function recover. // Cannot split the stack because it needs to reliably // find the stack segment of its caller. // // TODO(rsc): Once we commit to CopyStackAlways, // this doesn't need to be nosplit. // //go:nosplit func gorecover(argp uintptr) any { // Must be in a function running as part of a deferred call during the panic. // Must be called from the topmost function of the call // (the function used in the defer statement). // p.argp is the argument pointer of that topmost deferred function call. // Compare against argp reported by caller. // If they match, the caller is the one who can recover. gp := getg() p := gp._panic if p != nil && !p.goexit && !p.recovered && argp == uintptr(p.argp) { p.recovered = true return p.arg } return nil } //go:linkname sync_throw sync.throw func sync_throw(s string) { throw(s) } //go:linkname sync_fatal sync.fatal func sync_fatal(s string) { fatal(s) } // throw triggers a fatal error that dumps a stack trace and exits. // // throw should be used for runtime-internal fatal errors where Go itself, // rather than user code, may be at fault for the failure. // //go:nosplit func throw(s string) { // Everything throw does should be recursively nosplit so it // can be called even when it's unsafe to grow the stack. systemstack(func() { print("fatal error: ", s, "\n") }) fatalthrow(throwTypeRuntime) } // fatal triggers a fatal error that dumps a stack trace and exits. // // fatal is equivalent to throw, but is used when user code is expected to be // at fault for the failure, such as racing map writes. // // fatal does not include runtime frames, system goroutines, or frame metadata // (fp, sp, pc) in the stack trace unless GOTRACEBACK=system or higher. // //go:nosplit func fatal(s string) { // Everything fatal does should be recursively nosplit so it // can be called even when it's unsafe to grow the stack. systemstack(func() { print("fatal error: ", s, "\n") }) fatalthrow(throwTypeUser) } // runningPanicDefers is non-zero while running deferred functions for panic. // This is used to try hard to get a panic stack trace out when exiting. var runningPanicDefers atomic.Uint32 // panicking is non-zero when crashing the program for an unrecovered panic. var panicking atomic.Uint32 // paniclk is held while printing the panic information and stack trace, // so that two concurrent panics don't overlap their output. var paniclk mutex // Unwind the stack after a deferred function calls recover // after a panic. Then arrange to continue running as though // the caller of the deferred function returned normally. // // However, if unwinding the stack would skip over a Goexit call, we // return into the Goexit loop instead, so it can continue processing // defers instead. func recovery(gp *g) { p := gp._panic pc, sp, fp := p.retpc, uintptr(p.sp), uintptr(p.fp) p0, saveOpenDeferState := p, p.deferBitsPtr != nil && *p.deferBitsPtr != 0 // Unwind the panic stack. for ; p != nil && uintptr(p.startSP) < sp; p = p.link { // Don't allow jumping past a pending Goexit. // Instead, have its _panic.start() call return again. // // TODO(mdempsky): In this case, Goexit will resume walking the // stack where it left off, which means it will need to rewalk // frames that we've already processed. // // There's a similar issue with nested panics, when the inner // panic supercedes the outer panic. Again, we end up needing to // walk the same stack frames. // // These are probably pretty rare occurrences in practice, and // they don't seem any worse than the existing logic. But if we // move the unwinding state into _panic, we could detect when we // run into where the last panic started, and then just pick up // where it left off instead. // // With how subtle defer handling is, this might not actually be // worthwhile though. if p.goexit { pc, sp = p.startPC, uintptr(p.startSP) saveOpenDeferState = false // goexit is unwinding the stack anyway break } runningPanicDefers.Add(-1) } gp._panic = p if p == nil { // must be done with signal gp.sig = 0 } if gp.param != nil { throw("unexpected gp.param") } if saveOpenDeferState { // If we're returning to deferreturn and there are more open-coded // defers for it to call, save enough state for it to be able to // pick up where p0 left off. gp.param = unsafe.Pointer(&savedOpenDeferState{ retpc: p0.retpc, // We need to save deferBitsPtr and slotsPtr too, but those are // stack pointers. To avoid issues around heap objects pointing // to the stack, save them as offsets from SP. deferBitsOffset: uintptr(unsafe.Pointer(p0.deferBitsPtr)) - uintptr(p0.sp), slotsOffset: uintptr(p0.slotsPtr) - uintptr(p0.sp), }) } // TODO(mdempsky): Currently, we rely on frames containing "defer" // to end with "CALL deferreturn; RET". This allows deferreturn to // finish running any pending defers in the frame. // // But we should be able to tell whether there are still pending // defers here. If there aren't, we can just jump directly to the // "RET" instruction. And if there are, we don't need an actual // "CALL deferreturn" instruction; we can simulate it with something // like: // // if usesLR { // lr = pc // } else { // sp -= sizeof(pc) // *(*uintptr)(sp) = pc // } // pc = funcPC(deferreturn) // // So that we effectively tail call into deferreturn, such that it // then returns to the simple "RET" epilogue. That would save the // overhead of the "deferreturn" call when there aren't actually any // pending defers left, and shrink the TEXT size of compiled // binaries. (Admittedly, both of these are modest savings.) // Ensure we're recovering within the appropriate stack. if sp != 0 && (sp < gp.stack.lo || gp.stack.hi < sp) { print("recover: ", hex(sp), " not in [", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n") throw("bad recovery") } // Make the deferproc for this d return again, // this time returning 1. The calling function will // jump to the standard return epilogue. gp.sched.sp = sp gp.sched.pc = pc gp.sched.lr = 0 // Restore the bp on platforms that support frame pointers. // N.B. It's fine to not set anything for platforms that don't // support frame pointers, since nothing consumes them. switch { case goarch.IsAmd64 != 0: // on x86, fp actually points one word higher than the top of // the frame since the return address is saved on the stack by // the caller gp.sched.bp = fp - 2*goarch.PtrSize case goarch.IsArm64 != 0: // on arm64, the architectural bp points one word higher // than the sp. fp is totally useless to us here, because it // only gets us to the caller's fp. gp.sched.bp = sp - goarch.PtrSize } gp.sched.ret = 1 gogo(&gp.sched) } // fatalthrow implements an unrecoverable runtime throw. It freezes the // system, prints stack traces starting from its caller, and terminates the // process. // //go:nosplit func fatalthrow(t throwType) { pc := getcallerpc() sp := getcallersp() gp := getg() if gp.m.throwing == throwTypeNone { gp.m.throwing = t } // Switch to the system stack to avoid any stack growth, which may make // things worse if the runtime is in a bad state. systemstack(func() { if isSecureMode() { exit(2) } startpanic_m() if dopanic_m(gp, pc, sp) { // crash uses a decent amount of nosplit stack and we're already // low on stack in throw, so crash on the system stack (unlike // fatalpanic). crash() } exit(2) }) *(*int)(nil) = 0 // not reached } // fatalpanic implements an unrecoverable panic. It is like fatalthrow, except // that if msgs != nil, fatalpanic also prints panic messages and decrements // runningPanicDefers once main is blocked from exiting. // //go:nosplit func fatalpanic(msgs *_panic) { pc := getcallerpc() sp := getcallersp() gp := getg() var docrash bool // Switch to the system stack to avoid any stack growth, which // may make things worse if the runtime is in a bad state. systemstack(func() { if startpanic_m() && msgs != nil { // There were panic messages and startpanic_m // says it's okay to try to print them. // startpanic_m set panicking, which will // block main from exiting, so now OK to // decrement runningPanicDefers. runningPanicDefers.Add(-1) printpanics(msgs) } docrash = dopanic_m(gp, pc, sp) }) if docrash { // By crashing outside the above systemstack call, debuggers // will not be confused when generating a backtrace. // Function crash is marked nosplit to avoid stack growth. crash() } systemstack(func() { exit(2) }) *(*int)(nil) = 0 // not reached } // startpanic_m prepares for an unrecoverable panic. // // It returns true if panic messages should be printed, or false if // the runtime is in bad shape and should just print stacks. // // It must not have write barriers even though the write barrier // explicitly ignores writes once dying > 0. Write barriers still // assume that g.m.p != nil, and this function may not have P // in some contexts (e.g. a panic in a signal handler for a signal // sent to an M with no P). // //go:nowritebarrierrec func startpanic_m() bool { gp := getg() if mheap_.cachealloc.size == 0 { // very early print("runtime: panic before malloc heap initialized\n") } // Disallow malloc during an unrecoverable panic. A panic // could happen in a signal handler, or in a throw, or inside // malloc itself. We want to catch if an allocation ever does // happen (even if we're not in one of these situations). gp.m.mallocing++ // If we're dying because of a bad lock count, set it to a // good lock count so we don't recursively panic below. if gp.m.locks < 0 { gp.m.locks = 1 } switch gp.m.dying { case 0: // Setting dying >0 has the side-effect of disabling this G's writebuf. gp.m.dying = 1 panicking.Add(1) lock(&paniclk) if debug.schedtrace > 0 || debug.scheddetail > 0 { schedtrace(true) } freezetheworld() return true case 1: // Something failed while panicking. // Just print a stack trace and exit. gp.m.dying = 2 print("panic during panic\n") return false case 2: // This is a genuine bug in the runtime, we couldn't even // print the stack trace successfully. gp.m.dying = 3 print("stack trace unavailable\n") exit(4) fallthrough default: // Can't even print! Just exit. exit(5) return false // Need to return something. } } var didothers bool var deadlock mutex // gp is the crashing g running on this M, but may be a user G, while getg() is // always g0. func dopanic_m(gp *g, pc, sp uintptr) bool { if gp.sig != 0 { signame := signame(gp.sig) if signame != "" { print("[signal ", signame) } else { print("[signal ", hex(gp.sig)) } print(" code=", hex(gp.sigcode0), " addr=", hex(gp.sigcode1), " pc=", hex(gp.sigpc), "]\n") } level, all, docrash := gotraceback() if level > 0 { if gp != gp.m.curg { all = true } if gp != gp.m.g0 { print("\n") goroutineheader(gp) traceback(pc, sp, 0, gp) } else if level >= 2 || gp.m.throwing >= throwTypeRuntime { print("\nruntime stack:\n") traceback(pc, sp, 0, gp) } if !didothers && all { didothers = true tracebackothers(gp) } } unlock(&paniclk) if panicking.Add(-1) != 0 { // Some other m is panicking too. // Let it print what it needs to print. // Wait forever without chewing up cpu. // It will exit when it's done. lock(&deadlock) lock(&deadlock) } printDebugLog() return docrash } // canpanic returns false if a signal should throw instead of // panicking. // //go:nosplit func canpanic() bool { gp := getg() mp := acquirem() // Is it okay for gp to panic instead of crashing the program? // Yes, as long as it is running Go code, not runtime code, // and not stuck in a system call. if gp != mp.curg { releasem(mp) return false } // N.B. mp.locks != 1 instead of 0 to account for acquirem. if mp.locks != 1 || mp.mallocing != 0 || mp.throwing != throwTypeNone || mp.preemptoff != "" || mp.dying != 0 { releasem(mp) return false } status := readgstatus(gp) if status&^_Gscan != _Grunning || gp.syscallsp != 0 { releasem(mp) return false } if GOOS == "windows" && mp.libcallsp != 0 { releasem(mp) return false } releasem(mp) return true } // shouldPushSigpanic reports whether pc should be used as sigpanic's // return PC (pushing a frame for the call). Otherwise, it should be // left alone so that LR is used as sigpanic's return PC, effectively // replacing the top-most frame with sigpanic. This is used by // preparePanic. func shouldPushSigpanic(gp *g, pc, lr uintptr) bool { if pc == 0 { // Probably a call to a nil func. The old LR is more // useful in the stack trace. Not pushing the frame // will make the trace look like a call to sigpanic // instead. (Otherwise the trace will end at sigpanic // and we won't get to see who faulted.) return false } // If we don't recognize the PC as code, but we do recognize // the link register as code, then this assumes the panic was // caused by a call to non-code. In this case, we want to // ignore this call to make unwinding show the context. // // If we running C code, we're not going to recognize pc as a // Go function, so just assume it's good. Otherwise, traceback // may try to read a stale LR that looks like a Go code // pointer and wander into the woods. if gp.m.incgo || findfunc(pc).valid() { // This wasn't a bad call, so use PC as sigpanic's // return PC. return true } if findfunc(lr).valid() { // This was a bad call, but the LR is good, so use the // LR as sigpanic's return PC. return false } // Neither the PC or LR is good. Hopefully pushing a frame // will work. return true } // isAbortPC reports whether pc is the program counter at which // runtime.abort raises a signal. // // It is nosplit because it's part of the isgoexception // implementation. // //go:nosplit func isAbortPC(pc uintptr) bool { f := findfunc(pc) if !f.valid() { return false } return f.funcID == abi.FuncID_abort }
Upload File
Create Folder