1
0
mirror of https://github.com/golang/go synced 2024-11-24 14:20:13 -07:00

runtime: signal handling support for plan9_arm

Plan 9 trap/signal handling differs on ARM from other architectures
because ARM has a link register.  Also trap message syntax varies
between different architectures (historical accident?).
Revised 7 March to clarify a comment.

Change-Id: Ib6485f82857a2f9a0d6b2c375cf0aaa230b83656
Reviewed-on: https://go-review.googlesource.com/18969
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Richard Miller 2016-01-27 18:43:36 +00:00 committed by Brad Fitzpatrick
parent c97ddf9c10
commit d145456b16
5 changed files with 48 additions and 13 deletions

View File

@ -30,9 +30,13 @@ type sigctxt struct {
func (c *sigctxt) pc() uintptr { return uintptr(c.u.pc) } func (c *sigctxt) pc() uintptr { return uintptr(c.u.pc) }
func (c *sigctxt) sp() uintptr { return uintptr(c.u.sp) } func (c *sigctxt) sp() uintptr { return uintptr(c.u.sp) }
func (c *sigctxt) lr() uintptr { return uintptr(0) }
func (c *sigctxt) setpc(x uintptr) { c.u.pc = uint32(x) } func (c *sigctxt) setpc(x uintptr) { c.u.pc = uint32(x) }
func (c *sigctxt) setsp(x uintptr) { c.u.sp = uint32(x) } func (c *sigctxt) setsp(x uintptr) { c.u.sp = uint32(x) }
func (c *sigctxt) setlr(x uintptr) {}
func (c *sigctxt) savelr(x uintptr) {}
func dumpregs(u *ureg) { func dumpregs(u *ureg) {
print("ax ", hex(u.ax), "\n") print("ax ", hex(u.ax), "\n")
@ -49,3 +53,5 @@ func dumpregs(u *ureg) {
print("fs ", hex(u.fs), "\n") print("fs ", hex(u.fs), "\n")
print("gs ", hex(u.gs), "\n") print("gs ", hex(u.gs), "\n")
} }
func sigpanictramp() {}

View File

@ -39,9 +39,13 @@ type sigctxt struct {
func (c *sigctxt) pc() uintptr { return uintptr(c.u.ip) } func (c *sigctxt) pc() uintptr { return uintptr(c.u.ip) }
func (c *sigctxt) sp() uintptr { return uintptr(c.u.sp) } func (c *sigctxt) sp() uintptr { return uintptr(c.u.sp) }
func (c *sigctxt) lr() uintptr { return uintptr(0) }
func (c *sigctxt) setpc(x uintptr) { c.u.ip = uint64(x) } func (c *sigctxt) setpc(x uintptr) { c.u.ip = uint64(x) }
func (c *sigctxt) setsp(x uintptr) { c.u.sp = uint64(x) } func (c *sigctxt) setsp(x uintptr) { c.u.sp = uint64(x) }
func (c *sigctxt) setlr(x uintptr) {}
func (c *sigctxt) savelr(x uintptr) {}
func dumpregs(u *ureg) { func dumpregs(u *ureg) {
print("ax ", hex(u.ax), "\n") print("ax ", hex(u.ax), "\n")
@ -66,3 +70,5 @@ func dumpregs(u *ureg) {
print("fs ", hex(u.fs), "\n") print("fs ", hex(u.fs), "\n")
print("gs ", hex(u.gs), "\n") print("gs ", hex(u.gs), "\n")
} }
func sigpanictramp() {}

View File

@ -66,22 +66,37 @@ func sighandler(_ureg *ureg, note *byte, gp *g) int {
pc = 0 pc = 0
} }
// Only push sigpanic if PC != 0. // IF LR exists, sigpanictramp must save it to the stack
// // before entry to sigpanic so that panics in leaf
// functions are correctly handled. This will smash
// the stack frame but we're not going back there
// anyway.
if usesLR {
c.savelr(c.lr())
}
// If PC == 0, probably panicked because of a call to a nil func. // If PC == 0, probably panicked because of a call to a nil func.
// Not pushing that onto SP will make the trace look like a call // Not faking that as the return address will make the trace look like a call
// to sigpanic instead. (Otherwise the trace will end at // to sigpanic instead. (Otherwise the trace will end at
// sigpanic and we won't get to see who faulted). // sigpanic and we won't get to see who faulted).
if pc != 0 { if pc != 0 {
if sys.RegSize > sys.PtrSize { if usesLR {
c.setlr(pc)
} else {
if sys.RegSize > sys.PtrSize {
sp -= sys.PtrSize
*(*uintptr)(unsafe.Pointer(sp)) = 0
}
sp -= sys.PtrSize sp -= sys.PtrSize
*(*uintptr)(unsafe.Pointer(sp)) = 0 *(*uintptr)(unsafe.Pointer(sp)) = pc
c.setsp(sp)
} }
sp -= sys.PtrSize
*(*uintptr)(unsafe.Pointer(sp)) = pc
c.setsp(sp)
} }
c.setpc(funcPC(sigpanic)) if usesLR {
c.setpc(funcPC(sigpanictramp))
} else {
c.setpc(funcPC(sigpanic))
}
return _NCONT return _NCONT
} }
if flags&_SigNotify != 0 { if flags&_SigNotify != 0 {
@ -105,7 +120,7 @@ Throw:
level, _, docrash = gotraceback() level, _, docrash = gotraceback()
if level > 0 { if level > 0 {
goroutineheader(gp) goroutineheader(gp)
tracebacktrap(c.pc(), c.sp(), 0, gp) tracebacktrap(c.pc(), c.sp(), c.lr(), gp)
tracebackothers(gp) tracebackothers(gp)
print("\n") print("\n")
dumpregs(_ureg) dumpregs(_ureg)

View File

@ -78,7 +78,15 @@ func sigpanic() {
note := gostringnocopy((*byte)(unsafe.Pointer(g.m.notesig))) note := gostringnocopy((*byte)(unsafe.Pointer(g.m.notesig)))
switch g.sig { switch g.sig {
case _SIGRFAULT, _SIGWFAULT: case _SIGRFAULT, _SIGWFAULT:
addr := note[index(note, "addr=")+5:] i := index(note, "addr=")
if i >= 0 {
i += 5
} else if i = index(note, "va="); i >= 0 {
i += 3
} else {
panicmem()
}
addr := note[i:]
g.sigcode1 = uintptr(atolwhex(addr)) g.sigcode1 = uintptr(atolwhex(addr))
if g.sigcode1 < 0x1000 || g.paniconfault { if g.sigcode1 < 0x1000 || g.paniconfault {
panicmem() panicmem()

View File

@ -22,8 +22,8 @@ var sigtable = [...]sigTabT{
{_SigThrow, "sys: trap: invalid opcode"}, {_SigThrow, "sys: trap: invalid opcode"},
// We can recover from some memory errors in runtime·sigpanic. // We can recover from some memory errors in runtime·sigpanic.
{_SigPanic, "sys: trap: fault read addr"}, // SIGRFAULT {_SigPanic, "sys: trap: fault read"}, // SIGRFAULT
{_SigPanic, "sys: trap: fault write addr"}, // SIGWFAULT {_SigPanic, "sys: trap: fault write"}, // SIGWFAULT
// We can also recover from math errors. // We can also recover from math errors.
{_SigPanic, "sys: trap: divide error"}, // SIGINTDIV {_SigPanic, "sys: trap: divide error"}, // SIGINTDIV