1
0
mirror of https://github.com/golang/go synced 2024-11-07 04:16:10 -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:
Cherry Zhang 2021-04-30 19:45:11 -04:00
parent 844e1fc6f1
commit 8327d2150f
3 changed files with 71 additions and 48 deletions

View File

@ -13,10 +13,12 @@ import (
"cmd/compile/internal/base" "cmd/compile/internal/base"
"cmd/compile/internal/ir" "cmd/compile/internal/ir"
"cmd/compile/internal/liveness" "cmd/compile/internal/liveness"
"cmd/compile/internal/objw"
"cmd/compile/internal/ssagen" "cmd/compile/internal/ssagen"
"cmd/compile/internal/typecheck" "cmd/compile/internal/typecheck"
"cmd/compile/internal/types" "cmd/compile/internal/types"
"cmd/compile/internal/walk" "cmd/compile/internal/walk"
"cmd/internal/obj"
) )
// "Portable" code generation. // "Portable" code generation.
@ -47,6 +49,10 @@ func enqueueFunc(fn *ir.Func) {
a := ssagen.AbiForBodylessFuncStackMap(fn) a := ssagen.AbiForBodylessFuncStackMap(fn)
abiInfo := a.ABIAnalyzeFuncType(fn.Type().FuncType()) // abiInfo has spill/home locations for wrapper abiInfo := a.ABIAnalyzeFuncType(fn.Type().FuncType()) // abiInfo has spill/home locations for wrapper
liveness.WriteFuncMap(fn, abiInfo) 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 return
} }

View File

@ -6563,15 +6563,27 @@ func (s *State) DebugFriendlySetPosFrom(v *ssa.Value) {
} }
// emit argument info (locations on stack) for traceback. // 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() ft := e.curfn.Type()
if ft.NumRecvs() == 0 && ft.NumParams() == 0 { if ft.NumRecvs() == 0 && ft.NumParams() == 0 {
return 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 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) PtrSize := int64(types.PtrSize)
isAggregate := func(t *types.Type) bool { isAggregate := func(t *types.Type) bool {
@ -6696,27 +6708,19 @@ func emitArgInfo(e *ssafn, pp *objw.Progs) {
} }
c := true c := true
outer: for _, a := range abiInfo.InParams() {
for _, fs := range &types.RecvsParams { if !c {
for _, a := range fs(ft).Fields().Slice() { writebyte(_dotdotdot)
if !c { break
writebyte(_dotdotdot)
break outer
}
c = visitType(a.Offset, a.Type, 0)
} }
c = visitType(a.FrameOffset(abiInfo), a.Type, 0)
} }
writebyte(_endSeq) writebyte(_endSeq)
if wOff > maxLen { if wOff > maxLen {
base.Fatalf("ArgInfo too large") base.Fatalf("ArgInfo too large")
} }
// Emit a funcdata pointing at the arg info data. return x
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
} }
// genssa appends entries to pp for each instruction in f. // 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) e := f.Frontend().(*ssafn)
s.livenessMap, s.partLiveArgs = liveness.Compute(e.curfn, f, e.stkptrsize, pp) 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 openDeferInfo := e.curfn.LSym.Func().OpenCodedDeferInfo
if openDeferInfo != nil { if openDeferInfo != nil {

View File

@ -75,38 +75,51 @@ func Flushplist(ctxt *Link, plist *Plist, newprog ProgAlloc, myimportpath string
newprog = ctxt.NewProg newprog = ctxt.NewProg
} }
// Add reference to Go arguments for C or assembly functions without them. // Add reference to Go arguments for assembly functions without them.
for _, s := range text { if ctxt.IsAsm {
if !strings.HasPrefix(s.Name, "\"\".") { for _, s := range text {
continue if !strings.HasPrefix(s.Name, "\"\".") {
} continue
if s.ABIWrapper() { }
// Don't create an args_stackmap symbol reference for an ABI // The current args_stackmap generation in the compiler assumes
// wrapper function // that the function in question is ABI0, so avoid introducing
continue // an args_stackmap reference if the func is not ABI0 (better to
} // have no stackmap than an incorrect/lying stackmap).
// The current args_stackmap generation in the compiler assumes if s.ABI() != ABI0 {
// that the function in question is ABI0, so avoid introducing continue
// an args_stackmap reference if the func is not ABI0 (better to }
// have no stackmap than an incorrect/lying stackmap). foundArgMap, foundArgInfo := false, false
if s.ABI() != ABI0 { for p := s.Func().Text; p != nil; p = p.Link {
continue if p.As == AFUNCDATA && p.From.Type == TYPE_CONST {
} if p.From.Offset == objabi.FUNCDATA_ArgsPointerMaps {
found := false foundArgMap = true
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 { if p.From.Offset == objabi.FUNCDATA_ArgInfo {
found = true foundArgInfo = true
break }
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")
} }
} }