const usesLR … const tracebackInnerFrames … const tracebackOuterFrames … type unwindFlags … const unwindPrintErrors … const unwindSilentErrors … const unwindTrap … const unwindJumpStack … type unwinder … // init initializes u to start unwinding gp's stack and positions the // iterator on gp's innermost frame. gp must not be the current G. // // A single unwinder can be reused for multiple unwinds. func (u *unwinder) init(gp *g, flags unwindFlags) { … } func (u *unwinder) initAt(pc0, sp0, lr0 uintptr, gp *g, flags unwindFlags) { … } func (u *unwinder) valid() bool { … } // resolveInternal fills in u.frame based on u.frame.fn, pc, and sp. // // innermost indicates that this is the first resolve on this stack. If // innermost is set, isSyscall indicates that the PC/SP was retrieved from // gp.syscall*; this is otherwise ignored. // // On entry, u.frame contains: // - fn is the running function. // - pc is the PC in the running function. // - sp is the stack pointer at that program counter. // - For the innermost frame on LR machines, lr is the program counter that called fn. // // On return, u.frame contains: // - fp is the stack pointer of the caller. // - lr is the program counter that called fn. // - varp, argp, and continpc are populated for the current frame. // // If fn is a stack-jumping function, resolveInternal can change the entire // frame state to follow that stack jump. // // This is internal to unwinder. func (u *unwinder) resolveInternal(innermost, isSyscall bool) { … } func (u *unwinder) next() { … } // finishInternal is an unwinder-internal helper called after the stack has been // exhausted. It sets the unwinder to an invalid state and checks that it // successfully unwound the entire stack. func (u *unwinder) finishInternal() { … } // symPC returns the PC that should be used for symbolizing the current frame. // Specifically, this is the PC of the last instruction executed in this frame. // // If this frame did a normal call, then frame.pc is a return PC, so this will // return frame.pc-1, which points into the CALL instruction. If the frame was // interrupted by a signal (e.g., profiler, segv, etc) then frame.pc is for the // trapped instruction, so this returns frame.pc. See issue #34123. Finally, // frame.pc can be at function entry when the frame is initialized without // actually running code, like in runtime.mstart, in which case this returns // frame.pc because that's the best we can do. func (u *unwinder) symPC() uintptr { … } // cgoCallers populates pcBuf with the cgo callers of the current frame using // the registered cgo unwinder. It returns the number of PCs written to pcBuf. // If the current frame is not a cgo frame or if there's no registered cgo // unwinder, it returns 0. func (u *unwinder) cgoCallers(pcBuf []uintptr) int { … } // tracebackPCs populates pcBuf with the return addresses for each frame from u // and returns the number of PCs written to pcBuf. The returned PCs correspond // to "logical frames" rather than "physical frames"; that is if A is inlined // into B, this will still return a PCs for both A and B. This also includes PCs // generated by the cgo unwinder, if one is registered. // // If skip != 0, this skips this many logical frames. // // Callers should set the unwindSilentErrors flag on u. func tracebackPCs(u *unwinder, skip int, pcBuf []uintptr) int { … } // printArgs prints function arguments in traceback. func printArgs(f funcInfo, argp unsafe.Pointer, pc uintptr) { … } // funcNamePiecesForPrint returns the function name for printing to the user. // It returns three pieces so it doesn't need an allocation for string // concatenation. func funcNamePiecesForPrint(name string) (string, string, string) { … } // funcNameForPrint returns the function name for printing to the user. func funcNameForPrint(name string) string { … } // printFuncName prints a function name. name is the function name in // the binary's func data table. func printFuncName(name string) { … } func printcreatedby(gp *g) { … } func printcreatedby1(f funcInfo, pc uintptr, goid uint64) { … } func traceback(pc, sp, lr uintptr, gp *g) { … } // tracebacktrap is like traceback but expects that the PC and SP were obtained // from a trap, not from gp->sched or gp->syscallpc/gp->syscallsp or GetCallerPC/GetCallerSP. // Because they are from a trap instead of from a saved pair, // the initial PC must not be rewound to the previous instruction. // (All the saved pairs record a PC that is a return address, so we // rewind it into the CALL instruction.) // If gp.m.libcall{g,pc,sp} information is available, it uses that information in preference to // the pc/sp/lr passed in. func tracebacktrap(pc, sp, lr uintptr, gp *g) { … } func traceback1(pc, sp, lr uintptr, gp *g, flags unwindFlags) { … } // traceback2 prints a stack trace starting at u. It skips the first "skip" // logical frames, after which it prints at most "max" logical frames. It // returns n, which is the number of logical frames skipped and printed, and // lastN, which is the number of logical frames skipped or printed just in the // physical frame that u references. func traceback2(u *unwinder, showRuntime bool, skip, max int) (n, lastN int) { … } // printAncestorTraceback prints the traceback of the given ancestor. // TODO: Unify this with gentraceback and CallersFrames. func printAncestorTraceback(ancestor ancestorInfo) { … } // printAncestorTracebackFuncInfo prints the given function info at a given pc // within an ancestor traceback. The precision of this info is reduced // due to only have access to the pcs at the time of the caller // goroutine being created. func printAncestorTracebackFuncInfo(f funcInfo, pc uintptr) { … } // callers should be an internal detail, // (and is almost identical to Callers), // but widely used packages access it using linkname. // Notable members of the hall of shame include: // - github.com/phuslu/log // // Do not remove or change the type signature. // See go.dev/issue/67401. // //go:linkname callers func callers(skip int, pcbuf []uintptr) int { … } func gcallers(gp *g, skip int, pcbuf []uintptr) int { … } // showframe reports whether the frame with the given characteristics should // be printed during a traceback. func showframe(sf srcFunc, gp *g, firstFrame bool, calleeID abi.FuncID) bool { … } // showfuncinfo reports whether a function with the given characteristics should // be printed during a traceback. func showfuncinfo(sf srcFunc, firstFrame bool, calleeID abi.FuncID) bool { … } // isExportedRuntime reports whether name is an exported runtime function. // It is only for runtime functions, so ASCII A-Z is fine. func isExportedRuntime(name string) bool { … } // elideWrapperCalling reports whether a wrapper function that called // function id should be elided from stack traces. func elideWrapperCalling(id abi.FuncID) bool { … } var gStatusStrings … func goroutineheader(gp *g) { … } func tracebackothers(me *g) { … } // tracebackHexdump hexdumps part of stk around frame.sp and frame.fp // for debugging purposes. If the address bad is included in the // hexdumped range, it will mark it as well. func tracebackHexdump(stk stack, frame *stkframe, bad uintptr) { … } // isSystemGoroutine reports whether the goroutine g must be omitted // in stack dumps and deadlock detector. This is any goroutine that // starts at a runtime.* entry point, except for runtime.main, // runtime.handleAsyncEvent (wasm only) and sometimes runtime.runfinq. // // If fixed is true, any goroutine that can vary between user and // system (that is, the finalizer goroutine) is considered a user // goroutine. func isSystemGoroutine(gp *g, fixed bool) bool { … } // SetCgoTraceback records three C functions to use to gather // traceback information from C code and to convert that traceback // information into symbolic information. These are used when printing // stack traces for a program that uses cgo. // // The traceback and context functions may be called from a signal // handler, and must therefore use only async-signal safe functions. // The symbolizer function may be called while the program is // crashing, and so must be cautious about using memory. None of the // functions may call back into Go. // // The context function will be called with a single argument, a // pointer to a struct: // // struct { // Context uintptr // } // // In C syntax, this struct will be // // struct { // uintptr_t Context; // }; // // If the Context field is 0, the context function is being called to // record the current traceback context. It should record in the // Context field whatever information is needed about the current // point of execution to later produce a stack trace, probably the // stack pointer and PC. In this case the context function will be // called from C code. // // If the Context field is not 0, then it is a value returned by a // previous call to the context function. This case is called when the // context is no longer needed; that is, when the Go code is returning // to its C code caller. This permits the context function to release // any associated resources. // // While it would be correct for the context function to record a // complete a stack trace whenever it is called, and simply copy that // out in the traceback function, in a typical program the context // function will be called many times without ever recording a // traceback for that context. Recording a complete stack trace in a // call to the context function is likely to be inefficient. // // The traceback function will be called with a single argument, a // pointer to a struct: // // struct { // Context uintptr // SigContext uintptr // Buf *uintptr // Max uintptr // } // // In C syntax, this struct will be // // struct { // uintptr_t Context; // uintptr_t SigContext; // uintptr_t* Buf; // uintptr_t Max; // }; // // The Context field will be zero to gather a traceback from the // current program execution point. In this case, the traceback // function will be called from C code. // // Otherwise Context will be a value previously returned by a call to // the context function. The traceback function should gather a stack // trace from that saved point in the program execution. The traceback // function may be called from an execution thread other than the one // that recorded the context, but only when the context is known to be // valid and unchanging. The traceback function may also be called // deeper in the call stack on the same thread that recorded the // context. The traceback function may be called multiple times with // the same Context value; it will usually be appropriate to cache the // result, if possible, the first time this is called for a specific // context value. // // If the traceback function is called from a signal handler on a Unix // system, SigContext will be the signal context argument passed to // the signal handler (a C ucontext_t* cast to uintptr_t). This may be // used to start tracing at the point where the signal occurred. If // the traceback function is not called from a signal handler, // SigContext will be zero. // // Buf is where the traceback information should be stored. It should // be PC values, such that Buf[0] is the PC of the caller, Buf[1] is // the PC of that function's caller, and so on. Max is the maximum // number of entries to store. The function should store a zero to // indicate the top of the stack, or that the caller is on a different // stack, presumably a Go stack. // // Unlike runtime.Callers, the PC values returned should, when passed // to the symbolizer function, return the file/line of the call // instruction. No additional subtraction is required or appropriate. // // On all platforms, the traceback function is invoked when a call from // Go to C to Go requests a stack trace. On linux/amd64, linux/ppc64le, // linux/arm64, and freebsd/amd64, the traceback function is also invoked // when a signal is received by a thread that is executing a cgo call. // The traceback function should not make assumptions about when it is // called, as future versions of Go may make additional calls. // // The symbolizer function will be called with a single argument, a // pointer to a struct: // // struct { // PC uintptr // program counter to fetch information for // File *byte // file name (NUL terminated) // Lineno uintptr // line number // Func *byte // function name (NUL terminated) // Entry uintptr // function entry point // More uintptr // set non-zero if more info for this PC // Data uintptr // unused by runtime, available for function // } // // In C syntax, this struct will be // // struct { // uintptr_t PC; // char* File; // uintptr_t Lineno; // char* Func; // uintptr_t Entry; // uintptr_t More; // uintptr_t Data; // }; // // The PC field will be a value returned by a call to the traceback // function. // // The first time the function is called for a particular traceback, // all the fields except PC will be 0. The function should fill in the // other fields if possible, setting them to 0/nil if the information // is not available. The Data field may be used to store any useful // information across calls. The More field should be set to non-zero // if there is more information for this PC, zero otherwise. If More // is set non-zero, the function will be called again with the same // PC, and may return different information (this is intended for use // with inlined functions). If More is zero, the function will be // called with the next PC value in the traceback. When the traceback // is complete, the function will be called once more with PC set to // zero; this may be used to free any information. Each call will // leave the fields of the struct set to the same values they had upon // return, except for the PC field when the More field is zero. The // function must not keep a copy of the struct pointer between calls. // // When calling SetCgoTraceback, the version argument is the version // number of the structs that the functions expect to receive. // Currently this must be zero. // // The symbolizer function may be nil, in which case the results of // the traceback function will be displayed as numbers. If the // traceback function is nil, the symbolizer function will never be // called. The context function may be nil, in which case the // traceback function will only be called with the context field set // to zero. If the context function is nil, then calls from Go to C // to Go will not show a traceback for the C portion of the call stack. // // SetCgoTraceback should be called only once, ideally from an init function. func SetCgoTraceback(version int, traceback, context, symbolizer unsafe.Pointer) { … } var cgoTraceback … var cgoContext … var cgoSymbolizer … type cgoTracebackArg … type cgoContextArg … type cgoSymbolizerArg … // printCgoTraceback prints a traceback of callers. func printCgoTraceback(callers *cgoCallers) { … } // printOneCgoTraceback prints the traceback of a single cgo caller. // This can print more than one line because of inlining. // It returns the "stop" result of commitFrame. func printOneCgoTraceback(pc uintptr, commitFrame func() (pr, stop bool), arg *cgoSymbolizerArg) bool { … } // callCgoSymbolizer calls the cgoSymbolizer function. func callCgoSymbolizer(arg *cgoSymbolizerArg) { … } // cgoContextPCs gets the PC values from a cgo traceback. func cgoContextPCs(ctxt uintptr, buf []uintptr) { … }