// This is the entrypoint of the child process used by // TestTracebackSystem. It prints a crash report to stdout. func crash() { … } func child1() { … } func child2() { … } func child3() { … } func child4() { … } //go:noinline func child5() { … } //go:noinline func child6bad() { … } //go:noinline func child6() { … } //go:noinline func child7bad() { … } //go:noinline func child7() { … } // TestTracebackSystem tests that the syntax of crash reports produced // by GOTRACEBACK=system (see traceback2) contains a complete, // parseable list of program counters for the running goroutine that // can be parsed and fed to runtime.CallersFrames to obtain accurate // information about the logical call stack, even in the presence of // inlining. // // The test is a distillation of the crash monitor in // golang.org/x/telemetry/crashmonitor. func TestTracebackSystem(t *testing.T) { … } // parseStackPCs parses the parent process's program counters for the // first running goroutine out of a GOTRACEBACK=system traceback, // adjusting them so that they are valid for the child process's text // segment. // // This function returns only program counter values, ensuring that // there is no possibility of strings from the crash report (which may // contain PII) leaking into the telemetry system. // // (Copied from golang.org/x/telemetry/crashmonitor.parseStackPCs.) func parseStackPCs(crash string) ([]uintptr, error) { … } // The sentinel function returns its address. The difference between // this value as observed by calls in two different processes of the // same executable tells us the relative offset of their text segments. // // It would be nice if SetCrashOutput took care of this as it's fiddly // and likely to confuse every user at first. func sentinel() uint64 { … } func writeSentinel(out io.Writer) { … } // formatStack formats a stack of PC values using the symbol table, // redacting information that cannot be relied upon in the test. func formatStack(pcs []uintptr) string { … }