Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ch3.1: Broken under Go 1.12 (relocation target runtime.printstring not defined for ABI0 (but is defined for ABIInternal)) #427

Open
chai2010 opened this issue Mar 19, 2019 · 11 comments

Comments

@chai2010
Copy link
Owner

https://github.com/golang/proposal/blob/master/design/27539-internal-abi.md

@chai2010
Copy link
Owner Author

main.go

package main

var helloworld = "你好, 世界"

func main()

main.s:

TEXT ·main(SB), $16-0
	MOVQ ·helloworld+0(SB), AX; MOVQ AX, 0(SP)
	MOVQ ·helloworld+8(SB), BX; MOVQ BX, 8(SP)
	CALL runtime·printstring(SB)
	CALL runtime·printnl(SB)
	RET
$ go build
main.main: relocation target runtime.printstring not defined for ABI0 (but is defined for ABIInternal)
main.main: relocation target runtime.printnl not defined for ABI0 (but is defined for ABIInternal)

@chai2010
Copy link
Owner Author

go-qml/qml#190

@chai2010 chai2010 changed the title ch3.1: Broken under Go 1.12 (relocation target runtime.acquirem not defined for ABI0 (but is defined for ABIInternal)) ch3.1: Broken under Go 1.12 (relocation target runtime.printstring not defined for ABI0 (but is defined for ABIInternal)) Mar 19, 2019
@chai2010
Copy link
Owner Author

chai2010 commented Jul 3, 2019

这是第一节内容,目的是展示怎么自定义main函数。可以绕过变化到部分。

Go部分可以改成如下格式:

package main

import "fmt"

var helloworld = "你好, 世界"

func println(s string) {
	fmt.Println(s)
}

func main()

然后汇编部分:

TEXT ·main(SB), $16-0
    MOVQ ·helloworld+0(SB), AX; MOVQ AX, 0(SP)
    MOVQ ·helloworld+8(SB), BX; MOVQ BX, 8(SP)
    CALL ·println(SB)
    RET

在汇编实现中,main函数调用自定义到println函数实现打印。

@wangzhione
Copy link

Go 部分

main.go

package main

var helloWorld = "Hello, 世界"

func output(s string) {
	println(s)
}

func main()

汇编部分

main_amd64.s

TEXT ·main(SB), $16-0
    MOVQ ·helloWorld+0(SB), AX
    MOVQ AX, 0(SP)
    MOVQ ·helloWorld+8(SB), BX
    MOVQ BX, 8(SP)
    CALL ·output(SB)
    RET

也许更简单一点 ~

@chai2010 chai2010 mentioned this issue Sep 10, 2019
@xujunhai
Copy link

go1.14提示 missing function body

代码如下:main3.go
package main

import (
"fmt"
)

var helloWorld = "你好, 世界"
func println(s string) {
fmt.Println(s)
}
func main()

汇编文件 main3_amd64.s
//func main()
TEXT ·main(SB), $16-0
MOVQ ·helloWorld+0(SB),AX
MOVQ AX, 0(SP)
MOVQ ·helloWorld+8(SB),BX
MOVQ BX, 8(SP)
CALL ·println(SB)
RET

@hopehook
Copy link
Contributor

go1.14提示 missing function body

代码如下:main3.go package main

import ( "fmt" )

var helloWorld = "你好, 世界" func println(s string) { fmt.Println(s) } func main()

汇编文件 main3_amd64.s //func main() TEXT ·main(SB), $16-0 MOVQ ·helloWorld+0(SB),AX MOVQ AX, 0(SP) MOVQ ·helloWorld+8(SB),BX MOVQ BX, 8(SP) CALL ·println(SB) RET

go run 执行会报错, build 后再运行就可以了。

@feiquan123
Copy link

feiquan123 commented Jun 1, 2022

参考 compatibility section 这样写:

main.go

package main

import _ "unsafe"

//go:linkname printnl runtime.printnl
func printnl()

//go:linkname printstring runtime.printstring
func printstring(s string)

var helloWorld = "你好,世界"

func main()

main_amd64.s

TEXT ·main(SB), $16-0
	MOVQ ·helloWorld+0(SB), AX
	MOVQ AX, 0(SP)
	MOVQ ·helloWorld+8(SB), BX
	MOVQ BX, 8(SP)
	CALL runtime·printstring(SB)
	CALL runtime·printnl(SB)
	RET

@qshuai
Copy link

qshuai commented Jul 15, 2024

参考 compatibility section 这样写:

main.go

package main

import _ "unsafe"

//go:linkname printnl runtime.printnl
func printnl()

//go:linkname printstring runtime.printstring
func printstring(s string)

var helloWorld = "你好,世界"

func main()

main_amd64.s

TEXT ·main(SB), $16-0
	MOVQ ·helloWorld+0(SB), AX
	MOVQ AX, 0(SP)
	MOVQ ·helloWorld+8(SB), BX
	MOVQ BX, 8(SP)
	CALL runtime·printstring(SB)
	CALL runtime·printnl(SB)
	RET

为什么直接CALL方法(CALL ·printstring(SB); CALL ·printnl(SB))会报错?

main.main: relocation target main.printstring not defined
main.main: relocation target main.printnl not defined

求解答

@chai2010
Copy link
Owner Author

参考 compatibility section 这样写:

main.go

package main

import _ "unsafe"

//go:linkname printnl runtime.printnl
func printnl()

//go:linkname printstring runtime.printstring
func printstring(s string)

var helloWorld = "你好,世界"

func main()

main_amd64.s

TEXT ·main(SB), $16-0
	MOVQ ·helloWorld+0(SB), AX
	MOVQ AX, 0(SP)
	MOVQ ·helloWorld+8(SB), BX
	MOVQ BX, 8(SP)
	CALL runtime·printstring(SB)
	CALL runtime·printnl(SB)
	RET

为什么直接CALL方法(CALL ·printstring(SB); CALL ·printnl(SB))会报错?

main.main: relocation target main.printstring not defined
main.main: relocation target main.printnl not defined

求解答

runtime的内部函数不给调用了,哪怕是汇编代码。
参考 https://x.com/chaishushan/status/1805797136501817581

@qshuai
Copy link

qshuai commented Jul 16, 2024

参考 compatibility section 这样写:

main.go

package main

import _ "unsafe"

//go:linkname printnl runtime.printnl
func printnl()

//go:linkname printstring runtime.printstring
func printstring(s string)

var helloWorld = "你好,世界"

func main()

main_amd64.s

TEXT ·main(SB), $16-0
	MOVQ ·helloWorld+0(SB), AX
	MOVQ AX, 0(SP)
	MOVQ ·helloWorld+8(SB), BX
	MOVQ BX, 8(SP)
	CALL ·printstring(SB)
	CALL ·printnl(SB)
	RET

为什么直接CALL方法(CALL ·printstring(SB); CALL ·printnl(SB))会报错?

main.main: relocation target main.printstring not defined
main.main: relocation target main.printnl not defined

求解答

runtime的内部函数不给调用了,哪怕是汇编代码。 参考 https://x.com/chaishushan/status/1805797136501817581

大大,这个事情我了解过。但是和上面的问题没有对应起来哦。
我发现汇编中调用通过linkname关联的函数时,需要直接调用原函数(eg: runtime·printstring(SB)),而不能直接写linkname过来的函数(eg: ·printstring(SB))。

但是中转一下就可以了,不知道什么原理?下面的代码是OK的

# cat main.go
package main

import (
	_ "unsafe"
)

//go:linkname runtime_printnl runtime.printnl
func runtime_printnl()

func printnl() {
	runtime_printnl()
}

//go:linkname runtime_printstring runtime.printstring
func runtime_printstring(string)

func printstring(s string) {
	runtime_printstring(s)
}

var helloworld = "你好,世界"

func main()

$ cat main_amd64.s
TEXT ·main(SB),$16-0
  MOVQ ·helloworld+0(SB), AX
  MOVQ AX, 0(SP)
  MOVQ ·helloworld+8(SB), BX
  MOVQ BX, 8(SP)
  CALL runtime·printstring(SB)
  CALL runtime·printnl(SB)
  RET

@chai2010
Copy link
Owner Author

参考 compatibility section 这样写:

main.go

package main

import _ "unsafe"

//go:linkname printnl runtime.printnl
func printnl()

//go:linkname printstring runtime.printstring
func printstring(s string)

var helloWorld = "你好,世界"

func main()

main_amd64.s

TEXT ·main(SB), $16-0
	MOVQ ·helloWorld+0(SB), AX
	MOVQ AX, 0(SP)
	MOVQ ·helloWorld+8(SB), BX
	MOVQ BX, 8(SP)
	CALL runtime·printstring(SB)
	CALL runtime·printnl(SB)
	RET

为什么直接CALL方法(CALL ·printstring(SB); CALL ·printnl(SB))会报错?

main.main: relocation target main.printstring not defined
main.main: relocation target main.printnl not defined

求解答

runtime的内部函数不给调用了,哪怕是汇编代码。 参考 https://x.com/chaishushan/status/1805797136501817581

大大,这个事情我了解过。但是和上面的问题没有对应起来哦。 我发现汇编中调用通过linkname关联的函数时,需要直接调用原函数(eg: runtime·printstring(SB)),而不能直接写linkname过来的函数(eg: ·printstring(SB))。

但是中转一下就可以了,不知道什么原理?下面的代码是OK的

# cat main.go
package main

import (
	_ "unsafe"
)

//go:linkname runtime_printnl runtime.printnl
func runtime_printnl()

func printnl() {
	runtime_printnl()
}

//go:linkname runtime_printstring runtime.printstring
func runtime_printstring(string)

func printstring(s string) {
	runtime_printstring(s)
}

var helloworld = "你好,世界"

func main()

$ cat main_amd64.s
TEXT ·main(SB),$16-0
  MOVQ ·helloworld+0(SB), AX
  MOVQ AX, 0(SP)
  MOVQ ·helloworld+8(SB), BX
  MOVQ BX, 8(SP)
  CALL runtime·printstring(SB)
  CALL runtime·printnl(SB)
  RET

rsc的反馈表达了官方对内部api的态度。外部包尽量避免,负责后面被禁止也是有可能的。
至于中转下能否绕过我没有测试,底层检查实现本身都是比较容易的,这些都是编译器开的后门。
不是技术难不难实现,纯粹是官方的管理决定

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants