diff options
| author | Austin Clements <austin@google.com> | 2023-02-05 21:37:07 -0500 |
|---|---|---|
| committer | Austin Clements <austin@google.com> | 2023-03-10 17:18:34 +0000 |
| commit | 166e5ee4f2b5f170663c25b56d4929919c13debf (patch) | |
| tree | bba7627dc6de2e8e1e4a9516ff37e81f0e260fb3 /src/runtime/traceback.go | |
| parent | 59d0de16e4f003e69403eeee969f0b4a96dd6dcb (diff) | |
| download | go-166e5ee4f2b5f170663c25b56d4929919c13debf.tar.xz | |
runtime: use inlineUnwinder
This converts all places in the runtime that perform inline expansion
to use the new inlineUnwinder abstraction.
For #54466.
Change-Id: I48d996fb6263ed5225bd21d30914a27ae434528d
Reviewed-on: https://go-review.googlesource.com/c/go/+/466099
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Pratt <mpratt@google.com>
Diffstat (limited to 'src/runtime/traceback.go')
| -rw-r--r-- | src/runtime/traceback.go | 135 |
1 files changed, 48 insertions, 87 deletions
diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index e873ac74be..b4717ab164 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -306,9 +306,8 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in } if pcbuf != nil { - pc := frame.pc // backup to CALL instruction to read inlining info (same logic as below) - tracepc := pc + tracepc := frame.pc // Normally, pc is a return address. In that case, we want to look up // file/line information using pc-1, because that is the pc of the // call instruction (more precisely, the last byte of the call instruction). @@ -320,42 +319,24 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in // See issue 34123. // The pc can be at function entry when the frame is initialized without // actually running code, like runtime.mstart. - if (n == 0 && flags&_TraceTrap != 0) || calleeFuncID == funcID_sigpanic || pc == f.entry() { - pc++ - } else { + if !((n == 0 && flags&_TraceTrap != 0) || calleeFuncID == funcID_sigpanic || tracepc == f.entry()) { tracepc-- } - - // If there is inlining info, record the inner frames. - if inldata := funcdata(f, _FUNCDATA_InlTree); inldata != nil { - inltree := (*[1 << 20]inlinedCall)(inldata) - for { - ix := pcdatavalue(f, _PCDATA_InlTreeIndex, tracepc, &cache) - if ix < 0 { - break - } - if inltree[ix].funcID == funcID_wrapper && elideWrapperCalling(calleeFuncID) { - // ignore wrappers - } else if skip > 0 { - skip-- - } else if n < max { - (*[1 << 20]uintptr)(unsafe.Pointer(pcbuf))[n] = pc - n++ - } - calleeFuncID = inltree[ix].funcID - // Back up to an instruction in the "caller". - tracepc = frame.fn.entry() + uintptr(inltree[ix].parentPc) - pc = tracepc + 1 + // TODO: Why does cache escape? (Same below) + for iu, uf := newInlineUnwinder(f, tracepc, noEscapePtr(&cache)); uf.valid(); uf = iu.next(uf) { + sf := iu.srcFunc(uf) + if sf.funcID == funcID_wrapper && elideWrapperCalling(calleeFuncID) { + // ignore wrappers + } else if skip > 0 { + skip-- + } else if n < max { + // Callers expect the pc buffer to contain return addresses + // and do the -1 themselves, so we add 1 to the call PC to + // create a return PC. + (*[1 << 20]uintptr)(unsafe.Pointer(pcbuf))[n] = uf.pc + 1 + n++ } - } - // Record the main frame. - if f.funcID == funcID_wrapper && elideWrapperCalling(calleeFuncID) { - // Ignore wrapper functions (except when they trigger panics). - } else if skip > 0 { - skip-- - } else if n < max { - (*[1 << 20]uintptr)(unsafe.Pointer(pcbuf))[n] = pc - n++ + calleeFuncID = sf.funcID } n-- // offset n++ below } @@ -373,52 +354,38 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in if (n > 0 || flags&_TraceTrap == 0) && frame.pc > f.entry() && calleeFuncID != funcID_sigpanic { tracepc-- } - // If there is inlining info, print the inner frames. - if inldata := funcdata(f, _FUNCDATA_InlTree); inldata != nil { - inltree := (*[1 << 20]inlinedCall)(inldata) - for { - ix := pcdatavalue(f, _PCDATA_InlTreeIndex, tracepc, nil) - if ix < 0 { - break + for iu, uf := newInlineUnwinder(f, tracepc, noEscapePtr(&cache)); uf.valid(); uf = iu.next(uf) { + sf := iu.srcFunc(uf) + if (flags&_TraceRuntimeFrames) != 0 || showframe(sf, gp, nprint == 0, calleeFuncID) { + name := sf.name() + file, line := iu.fileLine(uf) + if name == "runtime.gopanic" { + name = "panic" } - - sf := srcFunc{f.datap, inltree[ix].nameOff, inltree[ix].startLine, inltree[ix].funcID} - - if (flags&_TraceRuntimeFrames) != 0 || showframe(sf, gp, nprint == 0, calleeFuncID) { - name := sf.name() - file, line := funcline(f, tracepc) - print(name, "(...)\n") - print("\t", file, ":", line, "\n") - nprint++ + // Print during crash. + // main(0x1, 0x2, 0x3) + // /home/rsc/go/src/runtime/x.go:23 +0xf + // + print(name, "(") + if iu.isInlined(uf) { + print("...") + } else { + argp := unsafe.Pointer(frame.argp) + printArgs(f, argp, tracepc) } - calleeFuncID = inltree[ix].funcID - // Back up to an instruction in the "caller". - tracepc = frame.fn.entry() + uintptr(inltree[ix].parentPc) - } - } - if (flags&_TraceRuntimeFrames) != 0 || showframe(f.srcFunc(), gp, nprint == 0, calleeFuncID) { - // Print during crash. - // main(0x1, 0x2, 0x3) - // /home/rsc/go/src/runtime/x.go:23 +0xf - // - name := funcname(f) - file, line := funcline(f, tracepc) - if name == "runtime.gopanic" { - name = "panic" - } - print(name, "(") - argp := unsafe.Pointer(frame.argp) - printArgs(f, argp, tracepc) - print(")\n") - print("\t", file, ":", line) - if frame.pc > f.entry() { - print(" +", hex(frame.pc-f.entry())) - } - if gp.m != nil && gp.m.throwing >= throwTypeRuntime && gp == gp.m.curg || level >= 2 { - print(" fp=", hex(frame.fp), " sp=", hex(frame.sp), " pc=", hex(frame.pc)) + print(")\n") + print("\t", file, ":", line) + if !iu.isInlined(uf) { + if frame.pc > f.entry() { + print(" +", hex(frame.pc-f.entry())) + } + if gp.m != nil && gp.m.throwing >= throwTypeRuntime && gp == gp.m.curg || level >= 2 { + print(" fp=", hex(frame.fp), " sp=", hex(frame.sp), " pc=", hex(frame.pc)) + } + } + print("\n") + nprint++ } - print("\n") - nprint++ } } n++ @@ -807,15 +774,9 @@ func printAncestorTraceback(ancestor ancestorInfo) { // due to only have access to the pcs at the time of the caller // goroutine being created. func printAncestorTracebackFuncInfo(f funcInfo, pc uintptr) { - name := funcname(f) - if inldata := funcdata(f, _FUNCDATA_InlTree); inldata != nil { - inltree := (*[1 << 20]inlinedCall)(inldata) - ix := pcdatavalue(f, _PCDATA_InlTreeIndex, pc, nil) - if ix >= 0 { - name = funcnameFromNameOff(f, inltree[ix].nameOff) - } - } - file, line := funcline(f, pc) + u, uf := newInlineUnwinder(f, pc, nil) + name := u.srcFunc(uf).name() + file, line := u.fileLine(uf) if name == "runtime.gopanic" { name = "panic" } |
