| // Copyright 2017 Marc-Antoine Ruel. All rights reserved. | |
| // Use of this source code is governed under the Apache License, Version 2.0 | |
| // that can be found in the LICENSE file. | |
| // panic crashes in various ways. | |
| // | |
| // It is a tool to help test pp, it is used in its unit tests. | |
| // | |
| // To install, run: | |
| // | |
| // go install github.com/maruel/panicparse/v2/cmd/panic | |
| // panic -help | |
| // panic str |& pp | |
| // | |
| // Some panics require the race detector with -race: | |
| // | |
| // go install -race github.com/maruel/panicparse/v2/cmd/panic | |
| // panic race |& pp | |
| // | |
| // To use with optimization (-N) and inlining (-l) disabled, build with | |
| // -gcflags '-N -l' like: | |
| // | |
| // go install -gcflags '-N -l' github.com/maruel/panicparse/v2/cmd/panic | |
| package main | |
| // To add a new panic stack signature, add it to types type below, keeping the | |
| // list ordered by name. If you need utility functions, add it in the section | |
| // below. That's it! | |
| import ( | |
| "fmt" | |
| "io" | |
| "os" | |
| "os/exec" | |
| "runtime" | |
| "sort" | |
| "strings" | |
| "sync" | |
| "time" | |
| "github.com/maruel/panicparse/v2/cmd/panic/internal" | |
| correct "github.com/maruel/panicparse/v2/cmd/panic/internal/incorrect" | |
| ùtf8 "github.com/maruel/panicparse/v2/cmd/panic/internal/utf8" | |
| ) | |
| func main() { | |
| if len(os.Args) == 2 { | |
| switch n := os.Args[1]; n { | |
| case "-h", "-help", "--help", "help": | |
| usage() | |
| os.Exit(0) | |
| case "dump_commands": | |
| // Undocumented command to do a raw dump of the supported commands. This | |
| // is used by unit tests in ../../stack. | |
| items := make([]string, 0, len(types)) | |
| for n := range types { | |
| items = append(items, n) | |
| } | |
| sort.Strings(items) | |
| for _, n := range items { | |
| fmt.Printf("%s\n", n) | |
| } | |
| os.Exit(0) | |
| default: | |
| if f, ok := types[n]; ok { | |
| fmt.Printf("GOTRACEBACK=%s\n", os.Getenv("GOTRACEBACK")) | |
| if n == "simple" { | |
| // Since the map lookup creates another call stack entry, add a | |
| // one-off "simple" panic style to test the very minimal case. | |
| // types["simple"].f is never called. | |
| panic("simple") | |
| } | |
| f.f() | |
| os.Exit(3) | |
| } | |
| fmt.Fprintf(stdErr, "unknown panic style %q\n", n) | |
| os.Exit(1) | |
| } | |
| } | |
| usage() | |
| os.Exit(1) | |
| } | |
| // Mocked in test. | |
| var stdErr io.Writer = os.Stderr | |
| // Utility functions. | |
| func panicint(i int) { | |
| panic(i) | |
| } | |
| func panicfloat64(f float64) { | |
| panic(f) | |
| } | |
| func panicstr(a string) { | |
| panic(a) | |
| } | |
| func panicslicestr(a []string) { | |
| panic(a) | |
| } | |
| func panicArgsElided(a, b, c, d, e, f, g, h, i, j, k int) { | |
| panic(a) | |
| } | |
| func recurse(i int) { | |
| if i > 0 { | |
| recurse(i - 1) | |
| return | |
| } | |
| panic(42) | |
| } | |
| func panicRaceDisabled(name string) { | |
| help := "'panic %s' can only be used when built with the race detector.\n" + | |
| "To build, use:\n" + | |
| " go install -race github.com/maruel/panicparse/v2/cmd/panic\n" | |
| fmt.Fprintf(stdErr, help, name) | |
| } | |
| func rerunWithFastCrash() { | |
| if os.Getenv("GORACE") != "log_path=stderr halt_on_error=1" { | |
| exe, err := os.Executable() | |
| if err != nil { | |
| fmt.Fprintln(stdErr, err) | |
| os.Exit(1) | |
| } | |
| c := exec.Command(exe, os.Args[1:]...) | |
| c.Env = append(os.Environ(), "GORACE=log_path=stderr halt_on_error=1") | |
| c.Stderr = os.Stderr | |
| if err := c.Run(); err != nil { | |
| if e, ok := err.(*exec.ExitError); ok { | |
| os.Exit(e.ExitCode()) | |
| } | |
| fmt.Fprintln(stdErr, err) | |
| os.Exit(1) | |
| } | |
| os.Exit(0) | |
| } | |
| } | |
| // panicDoRaceWrite and panicDoRaceRead are extracted from panicRace() to make | |
| // the stack trace less trivial, but in general folks will do the error with | |
| // this code inlined. | |
| func panicDoRaceWrite(x *int) { | |
| for i := 0; ; i++ { | |
| *x = i | |
| } | |
| } | |
| func panicDoRaceRead(x *int) { | |
| for i := 0; ; { | |
| i += *x | |
| } | |
| } | |
| func panicRace() { | |
| if !raceEnabled { | |
| panicRaceDisabled("race") | |
| return | |
| } | |
| rerunWithFastCrash() | |
| i := 0 | |
| // Do two separate calls so that the 'created at' stacks are different. | |
| go func() { | |
| panicDoRaceWrite(&i) | |
| }() | |
| go func() { | |
| panicDoRaceRead(&i) | |
| }() | |
| time.Sleep(time.Minute) | |
| } | |
| //go:noinline | |
| func panicChanStruct(x chan struct{}) { | |
| panic("test") | |
| } | |
| /* TODO(maruel): This is not detected! | |
| func panicRaceUnaligned() { | |
| if !raceEnabled { | |
| panicRaceDisabled("race_unaligned") | |
| return | |
| } | |
| rerunWithFastCrash() | |
| a := [8]byte{} | |
| b := (*int64)(unsafe.Pointer(&a[0])) | |
| go func() { | |
| for i := 0; ; i++ { | |
| a[4] = byte(i) | |
| } | |
| }() | |
| go func() { | |
| for { | |
| *b++ | |
| } | |
| }() | |
| time.Sleep(time.Minute) | |
| } | |
| */ | |
| // | |
| // types is all the supported types of panics. | |
| // | |
| // Keep the list sorted. | |
| // | |
| // TODO(maruel): Figure out a way to reliably trigger "(scan)" output: | |
| // - disable automatic GC with runtime.SetGCPercent(-1) | |
| // - a goroutine with a large number of items in the stack | |
| // - large heap to make the scanning process slow enough | |
| // - trigger a manual GC with go runtime.GC() | |
| // - panic in the meantime | |
| // This would still not be deterministic. | |
| // | |
| // TODO(maruel): Figure out a way to reliably trigger sleep output. | |
| var types = map[string]struct { | |
| desc string | |
| f func() | |
| }{ | |
| "args_elided": { | |
| "too many args in stack line, causing the call arguments to be elided", | |
| func() { | |
| panicArgsElided(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) | |
| }, | |
| }, | |
| "chan_receive": { | |
| "goroutine blocked on <-c", | |
| func() { | |
| c := make(chan bool) | |
| go func() { | |
| <-c | |
| <-c | |
| }() | |
| c <- true | |
| panic(42) | |
| }, | |
| }, | |
| "chan_send": { | |
| "goroutine blocked on c<-", | |
| func() { | |
| c := make(chan bool) | |
| go func() { | |
| c <- true | |
| c <- true | |
| }() | |
| <-c | |
| panic(42) | |
| }, | |
| }, | |
| "chan_struct": { | |
| "panic with an empty chan struct{} as a parameter", | |
| func() { | |
| panicChanStruct(nil) | |
| }, | |
| }, | |
| "float": { | |
| "panic(4.2)", | |
| func() { | |
| panicfloat64(4.2) | |
| }, | |
| }, | |
| "goroutine_1": { | |
| "panic in one goroutine", | |
| func() { | |
| go func() { | |
| panicint(42) | |
| }() | |
| time.Sleep(time.Minute) | |
| }, | |
| }, | |
| "goroutine_100": { | |
| "start 100 goroutines before panicking", | |
| func() { | |
| var wg sync.WaitGroup | |
| for i := 0; i < 100; i++ { | |
| wg.Add(1) | |
| go func() { | |
| wg.Done() | |
| time.Sleep(time.Minute) | |
| }() | |
| } | |
| wg.Wait() | |
| panicint(42) | |
| }, | |
| }, | |
| "goroutine_dedupe_pointers": { | |
| "start 100 goroutines with different pointers before panicking", | |
| func() { | |
| var wg sync.WaitGroup | |
| for i := 0; i < 100; i++ { | |
| wg.Add(1) | |
| go func(b *int) { | |
| wg.Done() | |
| time.Sleep(time.Minute) | |
| }(new(int)) | |
| } | |
| wg.Wait() | |
| panicint(42) | |
| }, | |
| }, | |
| "int": { | |
| "panic(42)", | |
| func() { | |
| panicint(42) | |
| }, | |
| }, | |
| "locked": { | |
| "thread locked goroutine via runtime.LockOSThread()", | |
| func() { | |
| runtime.LockOSThread() | |
| panic(42) | |
| }, | |
| }, | |
| "other": { | |
| "panics with other package in the call stack, with both exported and unexpected functions", | |
| func() { | |
| internal.Callback(func() { | |
| panic("allo") | |
| }) | |
| }, | |
| }, | |
| "asleep": { | |
| "panics with 'all goroutines are asleep - deadlock'", | |
| func() { | |
| // When built with the race detector, this hangs. I suspect this is due | |
| // because the race detector starts a separate goroutine which causes | |
| // checkdead() to not trigger. See checkdead() in src/runtime/proc.go. | |
| // https://github.com/golang/go/issues/20588 | |
| // | |
| // Repro: | |
| // go install -race github.com/maruel/panicparse/v2/cmd/panic; panic asleep | |
| var mu sync.Mutex | |
| mu.Lock() | |
| mu.Lock() | |
| }, | |
| }, | |
| "race": { | |
| "cause a crash by race detector", | |
| panicRace, | |
| }, | |
| /* TODO(maruel): This is not detected! | |
| "race_unaligned": { | |
| "cause a crash by race detector with unaligned access", | |
| panicRaceUnaligned, | |
| }, | |
| */ | |
| "stack_cut_off": { | |
| "recursive calls with too many call lines in traceback, causing higher up calls to missing", | |
| func() { | |
| // Observed limit is 99. | |
| // src/runtime/runtime2.go:const _TracebackMaxFrames = 100 | |
| recurse(100) | |
| }, | |
| }, | |
| "stack_cut_off_named": { | |
| "named calls with too many call lines in traceback, causing higher up calls to missing", | |
| func() { | |
| // The tool has difficulty with very deep static calls during linking. | |
| // See https://github.com/golang/go/issues/51814 | |
| recurse497() | |
| }, | |
| }, | |
| "simple": { | |
| // This is not used for real, here for documentation. | |
| "skip the map for a shorter stack trace", | |
| func() {}, | |
| }, | |
| "slice_str": { | |
| "panic([]string{\"allo\"}) with cap=2", | |
| func() { | |
| a := make([]string, 1, 2) | |
| a[0] = "allo" | |
| panicslicestr(a) | |
| }, | |
| }, | |
| "stdlib": { | |
| "panics with stdlib in the call stack, with both exported and unexpected functions", | |
| func() { | |
| strings.FieldsFunc("a", func(rune) bool { | |
| panic("allo") | |
| }) | |
| }, | |
| }, | |
| "stdlib_and_other": { | |
| "panics with both other and stdlib packages in the call stack", | |
| func() { | |
| strings.FieldsFunc("a", func(rune) bool { | |
| internal.Callback(func() { | |
| panic("allo") | |
| }) | |
| return false | |
| }) | |
| }, | |
| }, | |
| "str": { | |
| "panic(\"allo\")", | |
| func() { | |
| panicstr("allo") | |
| }, | |
| }, | |
| "mismatched": { | |
| "mismatched package and directory names", | |
| func() { | |
| correct.Panic() | |
| }, | |
| }, | |
| "utf8": { | |
| "non-ascii package, struct and method names", | |
| func() { | |
| s := ùtf8.Strùct{} | |
| s.Pànic() | |
| }, | |
| }, | |
| } | |
| func usage() { | |
| t := `usage: panic <way> | |
| This tool is meant to be used with pp to test different parsing scenarios and | |
| ensure output on different version of the Go toolchain can be successfully | |
| parsed. | |
| Set GOTRACEBACK before running this tool to see how it affects the panic output. | |
| Built with: ` + runtime.Version() + ` | |
| Select the way to panic: | |
| ` | |
| _, _ = io.WriteString(stdErr, t) | |
| names := make([]string, 0, len(types)) | |
| m := 0 | |
| for n := range types { | |
| names = append(names, n) | |
| if i := len(n); i > m { | |
| m = i | |
| } | |
| } | |
| sort.Strings(names) | |
| for _, n := range names { | |
| fmt.Fprintf(stdErr, "- %-*s %s\n", m, n, types[n].desc) | |
| } | |
| } | |
| // | |
| func recurse00() { panic("the end") } | |
| func recurse01() { recurse00() } | |
| func recurse02() { recurse01() } | |
| func recurse03() { recurse02() } | |
| func recurse04() { recurse03() } | |
| func recurse05() { recurse04() } | |
| func recurse06() { recurse05() } | |
| func recurse07() { recurse06() } | |
| func recurse08() { recurse07() } | |
| func recurse09() { recurse08() } | |
| func recurse10() { recurse09() } | |
| func recurse11() { recurse10() } | |
| func recurse12() { recurse11() } | |
| func recurse13() { recurse12() } | |
| func recurse14() { recurse13() } | |
| func recurse15() { recurse14() } | |
| func recurse16() { recurse15() } | |
| func recurse17() { recurse16() } | |
| func recurse18() { recurse17() } | |
| func recurse19() { recurse18() } | |
| func recurse20() { recurse19() } | |
| func recurse21() { recurse20() } | |
| func recurse22() { recurse21() } | |
| func recurse23() { recurse22() } | |
| func recurse24() { recurse23() } | |
| func recurse25() { recurse24() } | |
| func recurse26() { recurse25() } | |
| func recurse27() { recurse26() } | |
| func recurse28() { recurse27() } | |
| func recurse29() { recurse28() } | |
| func recurse30() { recurse29() } | |
| func recurse31() { recurse30() } | |
| func recurse32() { recurse31() } | |
| func recurse33() { recurse32() } | |
| func recurse34() { recurse33() } | |
| func recurse35() { recurse34() } | |
| func recurse36() { recurse35() } | |
| func recurse37() { recurse36() } | |
| func recurse38() { recurse37() } | |
| func recurse39() { recurse38() } | |
| func recurse40() { recurse39() } | |
| func recurse41() { recurse40() } | |
| func recurse42() { recurse41() } | |
| func recurse43() { recurse42() } | |
| func recurse44() { recurse43() } | |
| func recurse45() { recurse44() } | |
| func recurse46() { recurse45() } | |
| func recurse47() { recurse46() } | |
| func recurse48() { recurse47() } | |
| func recurse49() { recurse48() } | |
| func recurse50() { recurse49() } | |
| func recurse51() { recurse50() } | |
| func recurse52() { recurse51() } | |
| func recurse53() { recurse52() } | |
| func recurse54() { recurse53() } | |
| func recurse55() { recurse54() } | |
| func recurse56() { recurse55() } | |
| func recurse57() { recurse56() } | |
| func recurse58() { recurse57() } | |
| func recurse59() { recurse58() } | |
| func recurse60() { recurse59() } | |
| func recurse61() { recurse60() } | |
| func recurse62() { recurse61() } | |
| func recurse63() { recurse62() } | |
| func recurse64() { recurse63() } | |
| func recurse65() { recurse64() } | |
| func recurse66() { recurse65() } | |
| func recurse67() { recurse66() } | |
| func recurse68() { recurse67() } | |
| func recurse69() { recurse68() } | |
| func recurse70() { recurse69() } | |
| func recurse71() { recurse70() } | |
| func recurse72() { recurse71() } | |
| func recurse73() { recurse72() } | |
| func recurse74() { recurse73() } | |
| func recurse75() { recurse74() } | |
| func recurse76() { recurse75() } | |
| func recurse77() { recurse76() } | |
| func recurse78() { recurse77() } | |
| func recurse79() { recurse78() } | |
| func recurse80() { recurse79() } | |
| func recurse81() { recurse80() } | |
| func recurse82() { recurse81() } | |
| func recurse83() { recurse82() } | |
| func recurse84() { recurse83() } | |
| func recurse85() { recurse84() } | |
| func recurse86() { recurse85() } | |
| func recurse87() { recurse86() } | |
| func recurse88() { recurse87() } | |
| func recurse89() { recurse88() } | |
| func recurse90() { recurse89() } | |
| func recurse91() { recurse90() } | |
| func recurse92() { recurse91() } | |
| func recurse93() { recurse92() } | |
| func recurse94() { recurse93() } | |
| func recurse95() { recurse94() } | |
| func recurse96() { recurse95() } | |
| func recurse97() { recurse96() } | |
| func recurse98() { recurse97() } | |
| func recurse99() { recurse98() } | |
| func recurse100() { recurse99() } | |
| func recurse101() { recurse100() } | |
| func recurse102() { recurse101() } | |
| func recurse103() { recurse102() } | |
| func recurse104() { recurse103() } | |
| func recurse105() { recurse104() } | |
| func recurse106() { recurse105() } | |
| func recurse107() { recurse106() } | |
| func recurse108() { recurse107() } | |
| func recurse109() { recurse108() } | |
| func recurse110() { recurse109() } | |
| func recurse111() { recurse110() } | |
| func recurse112() { recurse111() } | |
| func recurse113() { recurse112() } | |
| func recurse114() { recurse113() } | |
| func recurse115() { recurse114() } | |
| func recurse116() { recurse115() } | |
| func recurse117() { recurse116() } | |
| func recurse118() { recurse117() } | |
| func recurse119() { recurse118() } | |
| func recurse120() { recurse119() } | |
| func recurse121() { recurse120() } | |
| func recurse122() { recurse121() } | |
| func recurse123() { recurse122() } | |
| func recurse124() { recurse123() } | |
| func recurse125() { recurse124() } | |
| func recurse126() { recurse125() } | |
| func recurse127() { recurse126() } | |
| func recurse128() { recurse127() } | |
| func recurse129() { recurse128() } | |
| func recurse130() { recurse129() } | |
| func recurse131() { recurse130() } | |
| func recurse132() { recurse131() } | |
| func recurse133() { recurse132() } | |
| func recurse134() { recurse133() } | |
| func recurse135() { recurse134() } | |
| func recurse136() { recurse135() } | |
| func recurse137() { recurse136() } | |
| func recurse138() { recurse137() } | |
| func recurse139() { recurse138() } | |
| func recurse140() { recurse139() } | |
| func recurse141() { recurse140() } | |
| func recurse142() { recurse141() } | |
| func recurse143() { recurse142() } | |
| func recurse144() { recurse143() } | |
| func recurse145() { recurse144() } | |
| func recurse146() { recurse145() } | |
| func recurse147() { recurse146() } | |
| func recurse148() { recurse147() } | |
| func recurse149() { recurse148() } | |
| func recurse150() { recurse149() } | |
| func recurse151() { recurse150() } | |
| func recurse152() { recurse151() } | |
| func recurse153() { recurse152() } | |
| func recurse154() { recurse153() } | |
| func recurse155() { recurse154() } | |
| func recurse156() { recurse155() } | |
| func recurse157() { recurse156() } | |
| func recurse158() { recurse157() } | |
| func recurse159() { recurse158() } | |
| func recurse160() { recurse159() } | |
| func recurse161() { recurse160() } | |
| func recurse162() { recurse161() } | |
| func recurse163() { recurse162() } | |
| func recurse164() { recurse163() } | |
| func recurse165() { recurse164() } | |
| func recurse166() { recurse165() } | |
| func recurse167() { recurse166() } | |
| func recurse168() { recurse167() } | |
| func recurse169() { recurse168() } | |
| func recurse170() { recurse169() } | |
| func recurse171() { recurse170() } | |
| func recurse172() { recurse171() } | |
| func recurse173() { recurse172() } | |
| func recurse174() { recurse173() } | |
| func recurse175() { recurse174() } | |
| func recurse176() { recurse175() } | |
| func recurse177() { recurse176() } | |
| func recurse178() { recurse177() } | |
| func recurse179() { recurse178() } | |
| func recurse180() { recurse179() } | |
| func recurse181() { recurse180() } | |
| func recurse182() { recurse181() } | |
| func recurse183() { recurse182() } | |
| func recurse184() { recurse183() } | |
| func recurse185() { recurse184() } | |
| func recurse186() { recurse185() } | |
| func recurse187() { recurse186() } | |
| func recurse188() { recurse187() } | |
| func recurse189() { recurse188() } | |
| func recurse190() { recurse189() } | |
| func recurse191() { recurse190() } | |
| func recurse192() { recurse191() } | |
| func recurse193() { recurse192() } | |
| func recurse194() { recurse193() } | |
| func recurse195() { recurse194() } | |
| func recurse196() { recurse195() } | |
| func recurse197() { recurse196() } | |
| func recurse198() { recurse197() } | |
| func recurse199() { recurse198() } | |
| func recurse200() { recurse199() } | |
| func recurse201() { recurse200() } | |
| func recurse202() { recurse201() } | |
| func recurse203() { recurse202() } | |
| func recurse204() { recurse203() } | |
| func recurse205() { recurse204() } | |
| func recurse206() { recurse205() } | |
| func recurse207() { recurse206() } | |
| func recurse208() { recurse207() } | |
| func recurse209() { recurse208() } | |
| func recurse210() { recurse209() } | |
| func recurse211() { recurse210() } | |
| func recurse212() { recurse211() } | |
| func recurse213() { recurse212() } | |
| func recurse214() { recurse213() } | |
| func recurse215() { recurse214() } | |
| func recurse216() { recurse215() } | |
| func recurse217() { recurse216() } | |
| func recurse218() { recurse217() } | |
| func recurse219() { recurse218() } | |
| func recurse220() { recurse219() } | |
| func recurse221() { recurse220() } | |
| func recurse222() { recurse221() } | |
| func recurse223() { recurse222() } | |
| func recurse224() { recurse223() } | |
| func recurse225() { recurse224() } | |
| func recurse226() { recurse225() } | |
| func recurse227() { recurse226() } | |
| func recurse228() { recurse227() } | |
| func recurse229() { recurse228() } | |
| func recurse230() { recurse229() } | |
| func recurse231() { recurse230() } | |
| func recurse232() { recurse231() } | |
| func recurse233() { recurse232() } | |
| func recurse234() { recurse233() } | |
| func recurse235() { recurse234() } | |
| func recurse236() { recurse235() } | |
| func recurse237() { recurse236() } | |
| func recurse238() { recurse237() } | |
| func recurse239() { recurse238() } | |
| func recurse240() { recurse239() } | |
| func recurse241() { recurse240() } | |
| func recurse242() { recurse241() } | |
| func recurse243() { recurse242() } | |
| func recurse244() { recurse243() } | |
| func recurse245() { recurse244() } | |
| func recurse246() { recurse245() } | |
| func recurse247() { recurse246() } | |
| func recurse248() { recurse247() } | |
| func recurse249() { recurse248() } | |
| func recurse250() { recurse249() } | |
| func recurse251() { recurse250() } | |
| func recurse252() { recurse251() } | |
| func recurse253() { recurse252() } | |
| func recurse254() { recurse253() } | |
| func recurse255() { recurse254() } | |
| func recurse256() { recurse255() } | |
| func recurse257() { recurse256() } | |
| func recurse258() { recurse257() } | |
| func recurse259() { recurse258() } | |
| func recurse260() { recurse259() } | |
| func recurse261() { recurse260() } | |
| func recurse262() { recurse261() } | |
| func recurse263() { recurse262() } | |
| func recurse264() { recurse263() } | |
| func recurse265() { recurse264() } | |
| func recurse266() { recurse265() } | |
| func recurse267() { recurse266() } | |
| func recurse268() { recurse267() } | |
| func recurse269() { recurse268() } | |
| func recurse270() { recurse269() } | |
| func recurse271() { recurse270() } | |
| func recurse272() { recurse271() } | |
| func recurse273() { recurse272() } | |
| func recurse274() { recurse273() } | |
| func recurse275() { recurse274() } | |
| func recurse276() { recurse275() } | |
| func recurse277() { recurse276() } | |
| func recurse278() { recurse277() } | |
| func recurse279() { recurse278() } | |
| func recurse280() { recurse279() } | |
| func recurse281() { recurse280() } | |
| func recurse282() { recurse281() } | |
| func recurse283() { recurse282() } | |
| func recurse284() { recurse283() } | |
| func recurse285() { recurse284() } | |
| func recurse286() { recurse285() } | |
| func recurse287() { recurse286() } | |
| func recurse288() { recurse287() } | |
| func recurse289() { recurse288() } | |
| func recurse290() { recurse289() } | |
| func recurse291() { recurse290() } | |
| func recurse292() { recurse291() } | |
| func recurse293() { recurse292() } | |
| func recurse294() { recurse293() } | |
| func recurse295() { recurse294() } | |
| func recurse296() { recurse295() } | |
| func recurse297() { recurse296() } | |
| func recurse298() { recurse297() } | |
| func recurse299() { recurse298() } | |
| func recurse300() { recurse299() } | |
| func recurse301() { recurse300() } | |
| func recurse302() { recurse301() } | |
| func recurse303() { recurse302() } | |
| func recurse304() { recurse303() } | |
| func recurse305() { recurse304() } | |
| func recurse306() { recurse305() } | |
| func recurse307() { recurse306() } | |
| func recurse308() { recurse307() } | |
| func recurse309() { recurse308() } | |
| func recurse310() { recurse309() } | |
| func recurse311() { recurse310() } | |
| func recurse312() { recurse311() } | |
| func recurse313() { recurse312() } | |
| func recurse314() { recurse313() } | |
| func recurse315() { recurse314() } | |
| func recurse316() { recurse315() } | |
| func recurse317() { recurse316() } | |
| func recurse318() { recurse317() } | |
| func recurse319() { recurse318() } | |
| func recurse320() { recurse319() } | |
| func recurse321() { recurse320() } | |
| func recurse322() { recurse321() } | |
| func recurse323() { recurse322() } | |
| func recurse324() { recurse323() } | |
| func recurse325() { recurse324() } | |
| func recurse326() { recurse325() } | |
| func recurse327() { recurse326() } | |
| func recurse328() { recurse327() } | |
| func recurse329() { recurse328() } | |
| func recurse330() { recurse329() } | |
| func recurse331() { recurse330() } | |
| func recurse332() { recurse331() } | |
| func recurse333() { recurse332() } | |
| func recurse334() { recurse333() } | |
| func recurse335() { recurse334() } | |
| func recurse336() { recurse335() } | |
| func recurse337() { recurse336() } | |
| func recurse338() { recurse337() } | |
| func recurse339() { recurse338() } | |
| func recurse340() { recurse339() } | |
| func recurse341() { recurse340() } | |
| func recurse342() { recurse341() } | |
| func recurse343() { recurse342() } | |
| func recurse344() { recurse343() } | |
| func recurse345() { recurse344() } | |
| func recurse346() { recurse345() } | |
| func recurse347() { recurse346() } | |
| func recurse348() { recurse347() } | |
| func recurse349() { recurse348() } | |
| func recurse350() { recurse349() } | |
| func recurse351() { recurse350() } | |
| func recurse352() { recurse351() } | |
| func recurse353() { recurse352() } | |
| func recurse354() { recurse353() } | |
| func recurse355() { recurse354() } | |
| func recurse356() { recurse355() } | |
| func recurse357() { recurse356() } | |
| func recurse358() { recurse357() } | |
| func recurse359() { recurse358() } | |
| func recurse360() { recurse359() } | |
| func recurse361() { recurse360() } | |
| func recurse362() { recurse361() } | |
| func recurse363() { recurse362() } | |
| func recurse364() { recurse363() } | |
| func recurse365() { recurse364() } | |
| func recurse366() { recurse365() } | |
| func recurse367() { recurse366() } | |
| func recurse368() { recurse367() } | |
| func recurse369() { recurse368() } | |
| func recurse370() { recurse369() } | |
| func recurse371() { recurse370() } | |
| func recurse372() { recurse371() } | |
| func recurse373() { recurse372() } | |
| func recurse374() { recurse373() } | |
| func recurse375() { recurse374() } | |
| func recurse376() { recurse375() } | |
| func recurse377() { recurse376() } | |
| func recurse378() { recurse377() } | |
| func recurse379() { recurse378() } | |
| func recurse380() { recurse379() } | |
| func recurse381() { recurse380() } | |
| func recurse382() { recurse381() } | |
| func recurse383() { recurse382() } | |
| func recurse384() { recurse383() } | |
| func recurse385() { recurse384() } | |
| func recurse386() { recurse385() } | |
| func recurse387() { recurse386() } | |
| func recurse388() { recurse387() } | |
| func recurse389() { recurse388() } | |
| func recurse390() { recurse389() } | |
| func recurse391() { recurse390() } | |
| func recurse392() { recurse391() } | |
| func recurse393() { recurse392() } | |
| func recurse394() { recurse393() } | |
| func recurse395() { recurse394() } | |
| func recurse396() { recurse395() } | |
| func recurse397() { recurse396() } | |
| func recurse398() { recurse397() } | |
| func recurse399() { recurse398() } | |
| func recurse400() { recurse399() } | |
| func recurse401() { recurse400() } | |
| func recurse402() { recurse401() } | |
| func recurse403() { recurse402() } | |
| func recurse404() { recurse403() } | |
| func recurse405() { recurse404() } | |
| func recurse406() { recurse405() } | |
| func recurse407() { recurse406() } | |
| func recurse408() { recurse407() } | |
| func recurse409() { recurse408() } | |
| func recurse410() { recurse409() } | |
| func recurse411() { recurse410() } | |
| func recurse412() { recurse411() } | |
| func recurse413() { recurse412() } | |
| func recurse414() { recurse413() } | |
| func recurse415() { recurse414() } | |
| func recurse416() { recurse415() } | |
| func recurse417() { recurse416() } | |
| func recurse418() { recurse417() } | |
| func recurse419() { recurse418() } | |
| func recurse420() { recurse419() } | |
| func recurse421() { recurse420() } | |
| func recurse422() { recurse421() } | |
| func recurse423() { recurse422() } | |
| func recurse424() { recurse423() } | |
| func recurse425() { recurse424() } | |
| func recurse426() { recurse425() } | |
| func recurse427() { recurse426() } | |
| func recurse428() { recurse427() } | |
| func recurse429() { recurse428() } | |
| func recurse430() { recurse429() } | |
| func recurse431() { recurse430() } | |
| func recurse432() { recurse431() } | |
| func recurse433() { recurse432() } | |
| func recurse434() { recurse433() } | |
| func recurse435() { recurse434() } | |
| func recurse436() { recurse435() } | |
| func recurse437() { recurse436() } | |
| func recurse438() { recurse437() } | |
| func recurse439() { recurse438() } | |
| func recurse440() { recurse439() } | |
| func recurse441() { recurse440() } | |
| func recurse442() { recurse441() } | |
| func recurse443() { recurse442() } | |
| func recurse444() { recurse443() } | |
| func recurse445() { recurse444() } | |
| func recurse446() { recurse445() } | |
| func recurse447() { recurse446() } | |
| func recurse448() { recurse447() } | |
| func recurse449() { recurse448() } | |
| func recurse450() { recurse449() } | |
| func recurse451() { recurse450() } | |
| func recurse452() { recurse451() } | |
| func recurse453() { recurse452() } | |
| func recurse454() { recurse453() } | |
| func recurse455() { recurse454() } | |
| func recurse456() { recurse455() } | |
| func recurse457() { recurse456() } | |
| func recurse458() { recurse457() } | |
| func recurse459() { recurse458() } | |
| func recurse460() { recurse459() } | |
| func recurse461() { recurse460() } | |
| func recurse462() { recurse461() } | |
| func recurse463() { recurse462() } | |
| func recurse464() { recurse463() } | |
| func recurse465() { recurse464() } | |
| func recurse466() { recurse465() } | |
| func recurse467() { recurse466() } | |
| func recurse468() { recurse467() } | |
| func recurse469() { recurse468() } | |
| func recurse470() { recurse469() } | |
| func recurse471() { recurse470() } | |
| func recurse472() { recurse471() } | |
| func recurse473() { recurse472() } | |
| func recurse474() { recurse473() } | |
| func recurse475() { recurse474() } | |
| func recurse476() { recurse475() } | |
| func recurse477() { recurse476() } | |
| func recurse478() { recurse477() } | |
| func recurse479() { recurse478() } | |
| func recurse480() { recurse479() } | |
| func recurse481() { recurse480() } | |
| func recurse482() { recurse481() } | |
| func recurse483() { recurse482() } | |
| func recurse484() { recurse483() } | |
| func recurse485() { recurse484() } | |
| func recurse486() { recurse485() } | |
| func recurse487() { recurse486() } | |
| func recurse488() { recurse487() } | |
| func recurse489() { recurse488() } | |
| func recurse490() { recurse489() } | |
| func recurse491() { recurse490() } | |
| func recurse492() { recurse491() } | |
| func recurse493() { recurse492() } | |
| func recurse494() { recurse493() } | |
| func recurse495() { recurse494() } | |
| func recurse496() { recurse495() } | |
| func recurse497() { recurse496() } |