mirror of
https://github.com/golang/go
synced 2024-11-23 05:30:07 -07:00
cmd/compile: add traceback argument info to ABI0 assembly functions
For ABI0 assembly functions that have Go declarations, generate traceback argument info and attach it to the assembly functions. So we can print argument in tracebacks if e.g. assembly function panics. Only do this for ABI0 functions, as for ABIInternal assembly functions it is likely that they never spill arguments to memory. Change-Id: I7e601ccd9aded5e6af2f02be975bf81ff9948f4d Reviewed-on: https://go-review.googlesource.com/c/go/+/315870 Trust: Cherry Zhang <cherryyz@google.com> Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
844e1fc6f1
commit
8327d2150f
@ -13,10 +13,12 @@ import (
|
||||
"cmd/compile/internal/base"
|
||||
"cmd/compile/internal/ir"
|
||||
"cmd/compile/internal/liveness"
|
||||
"cmd/compile/internal/objw"
|
||||
"cmd/compile/internal/ssagen"
|
||||
"cmd/compile/internal/typecheck"
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/compile/internal/walk"
|
||||
"cmd/internal/obj"
|
||||
)
|
||||
|
||||
// "Portable" code generation.
|
||||
@ -47,6 +49,10 @@ func enqueueFunc(fn *ir.Func) {
|
||||
a := ssagen.AbiForBodylessFuncStackMap(fn)
|
||||
abiInfo := a.ABIAnalyzeFuncType(fn.Type().FuncType()) // abiInfo has spill/home locations for wrapper
|
||||
liveness.WriteFuncMap(fn, abiInfo)
|
||||
if fn.ABI == obj.ABI0 {
|
||||
x := ssagen.EmitArgInfo(fn, abiInfo)
|
||||
objw.Global(x, int32(len(x.P)), obj.RODATA|obj.LOCAL)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -6563,15 +6563,27 @@ func (s *State) DebugFriendlySetPosFrom(v *ssa.Value) {
|
||||
}
|
||||
|
||||
// emit argument info (locations on stack) for traceback.
|
||||
func emitArgInfo(e *ssafn, pp *objw.Progs) {
|
||||
func emitArgInfo(e *ssafn, f *ssa.Func, pp *objw.Progs) {
|
||||
ft := e.curfn.Type()
|
||||
if ft.NumRecvs() == 0 && ft.NumParams() == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
x := base.Ctxt.Lookup(fmt.Sprintf("%s.arginfo%d", e.curfn.LSym.Name, e.curfn.LSym.ABI()))
|
||||
x := EmitArgInfo(e.curfn, f.OwnAux.ABIInfo())
|
||||
e.curfn.LSym.Func().ArgInfo = x
|
||||
|
||||
// Emit a funcdata pointing at the arg info data.
|
||||
p := pp.Prog(obj.AFUNCDATA)
|
||||
p.From.SetConst(objabi.FUNCDATA_ArgInfo)
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Name = obj.NAME_EXTERN
|
||||
p.To.Sym = x
|
||||
}
|
||||
|
||||
// emit argument info (locations on stack) of f for traceback.
|
||||
func EmitArgInfo(f *ir.Func, abiInfo *abi.ABIParamResultInfo) *obj.LSym {
|
||||
x := base.Ctxt.Lookup(fmt.Sprintf("%s.arginfo%d", f.LSym.Name, f.ABI))
|
||||
|
||||
PtrSize := int64(types.PtrSize)
|
||||
|
||||
isAggregate := func(t *types.Type) bool {
|
||||
@ -6696,27 +6708,19 @@ func emitArgInfo(e *ssafn, pp *objw.Progs) {
|
||||
}
|
||||
|
||||
c := true
|
||||
outer:
|
||||
for _, fs := range &types.RecvsParams {
|
||||
for _, a := range fs(ft).Fields().Slice() {
|
||||
if !c {
|
||||
writebyte(_dotdotdot)
|
||||
break outer
|
||||
}
|
||||
c = visitType(a.Offset, a.Type, 0)
|
||||
for _, a := range abiInfo.InParams() {
|
||||
if !c {
|
||||
writebyte(_dotdotdot)
|
||||
break
|
||||
}
|
||||
c = visitType(a.FrameOffset(abiInfo), a.Type, 0)
|
||||
}
|
||||
writebyte(_endSeq)
|
||||
if wOff > maxLen {
|
||||
base.Fatalf("ArgInfo too large")
|
||||
}
|
||||
|
||||
// Emit a funcdata pointing at the arg info data.
|
||||
p := pp.Prog(obj.AFUNCDATA)
|
||||
p.From.SetConst(objabi.FUNCDATA_ArgInfo)
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Name = obj.NAME_EXTERN
|
||||
p.To.Sym = x
|
||||
return x
|
||||
}
|
||||
|
||||
// genssa appends entries to pp for each instruction in f.
|
||||
@ -6727,7 +6731,7 @@ func genssa(f *ssa.Func, pp *objw.Progs) {
|
||||
e := f.Frontend().(*ssafn)
|
||||
|
||||
s.livenessMap, s.partLiveArgs = liveness.Compute(e.curfn, f, e.stkptrsize, pp)
|
||||
emitArgInfo(e, pp)
|
||||
emitArgInfo(e, f, pp)
|
||||
|
||||
openDeferInfo := e.curfn.LSym.Func().OpenCodedDeferInfo
|
||||
if openDeferInfo != nil {
|
||||
|
@ -75,38 +75,51 @@ func Flushplist(ctxt *Link, plist *Plist, newprog ProgAlloc, myimportpath string
|
||||
newprog = ctxt.NewProg
|
||||
}
|
||||
|
||||
// Add reference to Go arguments for C or assembly functions without them.
|
||||
for _, s := range text {
|
||||
if !strings.HasPrefix(s.Name, "\"\".") {
|
||||
continue
|
||||
}
|
||||
if s.ABIWrapper() {
|
||||
// Don't create an args_stackmap symbol reference for an ABI
|
||||
// wrapper function
|
||||
continue
|
||||
}
|
||||
// The current args_stackmap generation in the compiler assumes
|
||||
// that the function in question is ABI0, so avoid introducing
|
||||
// an args_stackmap reference if the func is not ABI0 (better to
|
||||
// have no stackmap than an incorrect/lying stackmap).
|
||||
if s.ABI() != ABI0 {
|
||||
continue
|
||||
}
|
||||
found := false
|
||||
for p := s.Func().Text; p != nil; p = p.Link {
|
||||
if p.As == AFUNCDATA && p.From.Type == TYPE_CONST && p.From.Offset == objabi.FUNCDATA_ArgsPointerMaps {
|
||||
found = true
|
||||
break
|
||||
// Add reference to Go arguments for assembly functions without them.
|
||||
if ctxt.IsAsm {
|
||||
for _, s := range text {
|
||||
if !strings.HasPrefix(s.Name, "\"\".") {
|
||||
continue
|
||||
}
|
||||
// The current args_stackmap generation in the compiler assumes
|
||||
// that the function in question is ABI0, so avoid introducing
|
||||
// an args_stackmap reference if the func is not ABI0 (better to
|
||||
// have no stackmap than an incorrect/lying stackmap).
|
||||
if s.ABI() != ABI0 {
|
||||
continue
|
||||
}
|
||||
foundArgMap, foundArgInfo := false, false
|
||||
for p := s.Func().Text; p != nil; p = p.Link {
|
||||
if p.As == AFUNCDATA && p.From.Type == TYPE_CONST {
|
||||
if p.From.Offset == objabi.FUNCDATA_ArgsPointerMaps {
|
||||
foundArgMap = true
|
||||
}
|
||||
if p.From.Offset == objabi.FUNCDATA_ArgInfo {
|
||||
foundArgInfo = true
|
||||
}
|
||||
if foundArgMap && foundArgInfo {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !foundArgMap {
|
||||
p := Appendp(s.Func().Text, newprog)
|
||||
p.As = AFUNCDATA
|
||||
p.From.Type = TYPE_CONST
|
||||
p.From.Offset = objabi.FUNCDATA_ArgsPointerMaps
|
||||
p.To.Type = TYPE_MEM
|
||||
p.To.Name = NAME_EXTERN
|
||||
p.To.Sym = ctxt.LookupDerived(s, s.Name+".args_stackmap")
|
||||
}
|
||||
if !foundArgInfo {
|
||||
p := Appendp(s.Func().Text, newprog)
|
||||
p.As = AFUNCDATA
|
||||
p.From.Type = TYPE_CONST
|
||||
p.From.Offset = objabi.FUNCDATA_ArgInfo
|
||||
p.To.Type = TYPE_MEM
|
||||
p.To.Name = NAME_EXTERN
|
||||
p.To.Sym = ctxt.LookupDerived(s, fmt.Sprintf("%s.arginfo%d", s.Name, s.ABI()))
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
p := Appendp(s.Func().Text, newprog)
|
||||
p.As = AFUNCDATA
|
||||
p.From.Type = TYPE_CONST
|
||||
p.From.Offset = objabi.FUNCDATA_ArgsPointerMaps
|
||||
p.To.Type = TYPE_MEM
|
||||
p.To.Name = NAME_EXTERN
|
||||
p.To.Sym = ctxt.LookupDerived(s, s.Name+".args_stackmap")
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user