Panic from golang's assembler function

Hi,

I encountered a minor trouble: panic called from a golang’s assembly function doesn’t work completely.

The motivation is as follows:
I want the highly-optimized code for vector inner product code, hence, its code should check the length of the two vectors equal, and reports the error with panic.
When I wrap the assembly code with golang’s function for panic, the overhead at the entry and exit process (runtime.morestack_noctxt, etc) makes the calculation slow down (profiler reports that they took more than a second …).

In order to show my problem, I wrote a PoC code.
At first, I wrote the following assembly code:

#include "funcdata.h"
#include "textflag.h"

// func panicPanic()
TEXT ·panicPanic(SB), NOSPLIT, $0-0
        SUBQ    $8, SP
        MOVQ    BP, 0(SP)
        LEAQ    0(SP), BP
        MOVQ    ·panicMessage(SB), AX
        MOVQ    ·panicMessage+8(SB), CX
        TESTQ   AX, AX
        JEQ     panic1
        MOVQ    8(AX), AX
panic1:
        MOVQ    AX, (SP)
        MOVQ    CX, 8(SP)
        CALL    runtime·gopanic(SB)

Then, I build and run the following golang’s code on golang 1.10.3 and macOS 10.13.5:

package main

import "fmt"

var panicMessage = fmt.Errorf("Panic panic")

func panicPanic()

func tryPanic() {
	defer func() {
		fmt.Printf("recovered: %s\n", recover())
	}()
	panicPanic()
}

func main() {
	tryPanic()
	panicPanic()
}

I found that recover works expectedly, however, the backtrace triggered by runtime.gopanic called at panicPanic didn’t work expectedly:

recovered: Panic panic
panic: Panic panic

goroutine 1 [running]:
runtime: unexpected return pc for runtime.gopanic called from 0x108f261
stack: frame={sp:0xc420045ec8, fp:0xc420045f68} stack=[0xc420044000,0xc420046000)
000000c420045dc8:  00000000010489a2 <runtime.writeErr+66>  0000000000000002
000000c420045dd8:  00000000010c0147  0000000000000001
000000c420045de8:  000000c400000001  000000c420045e28
000000c420045df8:  0000000001026b08 <runtime.gwrite+280>  00000000010c0147
000000c420045e08:  0000000000000001  0000000000000001
000000c420045e18:  0000000001026b08 <runtime.gwrite+280>  00000000010c0748
000000c420045e28:  000000c420045e78  00000000010272bd <runtime.printstring+125>
000000c420045e38:  00000000010c0147  0000000000000001
000000c420045e48:  0000000000000001  00000000010c0147
000000c420045e58:  0000000000000001  00000000010c0147
000000c420045e68:  0000000000000001  0000000000000001
000000c420045e78:  000000c420045e98  000000c420045e98
000000c420045e88:  0000000001025f7a <runtime.dopanic+74>  000000c420045e98
000000c420045e98:  000000000104a330 <runtime.dopanic.func1+0>  000000c420000180
000000c420045ea8:  0000000001025bb1 <runtime.gopanic+961>  000000c420045ec8
000000c420045eb8:  000000c420045f58  0000000001025bb1 <runtime.gopanic+961>
000000c420045ec8: <0000000000000000  00000000010c70a8
000000c420045ed8:  000000c420056030  0000000800000008
000000c420045ee8:  00000000010277b1 <runtime.main+257>  000000c42007e1a0
000000c420045ef8:  000000c420045f88  000000c420000180
000000c420045f08:  000000c4200001a0  000000c420056020
000000c420045f18:  000000c420056000  000000c4200001a8
000000c420045f28:  000000c4200001a0  0000000000000000
000000c420045f38:  000000000109f220  000000c42007a1d0
000000c420045f48:  0000000000000000  0000000000000000
000000c420045f58:  000000c420045f68 !000000000108f261
000000c420045f68: >00000000010a5c40  000000c42007a1c0
000000c420045f78:  00007fffffe00000  00000000010278c2 <runtime.main+530>
000000c420045f88:  000000c420078000  0000000000000000
000000c420045f98:  000000c420078000  0000000000000000
000000c420045fa8:  0000000000000000  0000000000000000
000000c420045fb8:  0000000000000000  0000000000000000
000000c420045fc8:  000000c420000180  0000000000000000
000000c420045fd8:  000000000104d981 <runtime.goexit+1>  0000000000000000
000000c420045fe8:  0000000000000000  0000000000000000
000000c420045ff8:  0000000000000000
runtime: unexpected return pc for runtime.gopanic called from 0x108f261
stack: frame={sp:0xc420045ec8, fp:0xc420045f68} stack=[0xc420044000,0xc420046000)
000000c420045dc8:  00000000010489a2 <runtime.writeErr+66>  0000000000000002
000000c420045dd8:  00000000010c0147  0000000000000001
000000c420045de8:  000000c400000001  000000c420045e28
000000c420045df8:  0000000001026b08 <runtime.gwrite+280>  00000000010c0147
000000c420045e08:  0000000000000001  0000000000000001
000000c420045e18:  0000000001026b08 <runtime.gwrite+280>  00000000010c0748
000000c420045e28:  000000c420045e78  00000000010272bd <runtime.printstring+125>
000000c420045e38:  00000000010c0147  0000000000000001
000000c420045e48:  0000000000000001  00000000010c0147
000000c420045e58:  0000000000000001  00000000010c0147
000000c420045e68:  0000000000000001  0000000000000001
000000c420045e78:  000000c420045e98  000000c420045e98
000000c420045e88:  0000000001025f7a <runtime.dopanic+74>  000000c420045e98
000000c420045e98:  000000000104a330 <runtime.dopanic.func1+0>  000000c420000180
000000c420045ea8:  0000000001025bb1 <runtime.gopanic+961>  000000c420045ec8
000000c420045eb8:  000000c420045f58  0000000001025bb1 <runtime.gopanic+961>
000000c420045ec8: <0000000000000000  00000000010c70a8
000000c420045ed8:  000000c420056030  0000000800000008
000000c420045ee8:  00000000010277b1 <runtime.main+257>  000000c42007e1a0
000000c420045ef8:  000000c420045f88  000000c420000180
000000c420045f08:  000000c4200001a0  000000c420056020
000000c420045f18:  000000c420056000  000000c4200001a8
000000c420045f28:  000000c4200001a0  0000000000000000
000000c420045f38:  000000000109f220  000000c42007a1d0
000000c420045f48:  0000000000000000  0000000000000000
000000c420045f58:  000000c420045f68 !000000000108f261
000000c420045f68: >00000000010a5c40  000000c42007a1c0
000000c420045f78:  00007fffffe00000  00000000010278c2 <runtime.main+530>
000000c420045f88:  000000c420078000  0000000000000000
000000c420045f98:  000000c420078000  0000000000000000
000000c420045fa8:  0000000000000000  0000000000000000
000000c420045fb8:  0000000000000000  0000000000000000
000000c420045fc8:  000000c420000180  0000000000000000
000000c420045fd8:  000000000104d981 <runtime.goexit+1>  0000000000000000
000000c420045fe8:  0000000000000000  0000000000000000
000000c420045ff8:  0000000000000000
panic(0x10a5c40, 0xc42007a1c0)
	/usr/local/go/src/runtime/panic.go:551 +0x3c1

I doubt that this is because the runtime.gopanic call from a assembly function is not registered (see https://github.com/golang/go/blob/0e0cd70ecf6b5f0d9c8271f68b8fcc9f85cd6598/src/runtime/traceback.go#L257).
I think the backtrace implementation detected that the call stack was broken.

I tried some options funcdata.h or textflag.h as referring to the assembly code generated by golang’s compiler, but I didn’t find a solution.
I searched this problem on web also, but, I didn’t find any solution…

If you have any idea, please tell me your solution!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.