返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

编译

发布于 2024-10-12 19:16:09 字数 2875 浏览 0 评论 0 收藏 0

编译不仅仅是执行 go build 命令,还有些额外内容。

  • 调试-gcflags "-N -l" ,阻止优化和内联。
  • 发布-ldflags "-w -s" ,剔除符号表和调试信息。

1. 编译指令

编译指令(#pragmas)非语言规范内容,由编译器实现,指示对代码做 “特殊” 处理。

  • //go:noinline : 阻止内联。
  • //go:nosplit : 不插入 morestack 指令。(栈检查和扩容)

注意, //go 之间不能有空格,避免和注释(comment)冲突。

使用编译指令阻止具体某个函数内联,这与 -gcflags "-l" 全局不同。

package main

//go:noinline
//go:nosplit
func test() {
	println("hello, world!")
}

func main() {
	test();
}
$ go build -o test
$ go tool objdump -s "main\.test" ./test

TEXT main.test(SB)
  main.go:5		SUBQ $0x18, SP			
  main.go:5		MOVQ BP, 0x10(SP)		
  main.go:5		LEAQ 0x10(SP), BP	
  
  main.go:6		CALL runtime.printlock(SB)	
  main.go:6		LEAQ 0xd7a4(IP), AX		
  main.go:6		MOVL $0xe, BX			
  main.go:6		NOPL				
  main.go:6		CALL runtime.printstring(SB)	
  main.go:6		CALL runtime.printunlock(SB)	
  
  main.go:7		MOVQ 0x10(SP), BP		
  main.go:7		ADDQ $0x18, SP			
  main.go:7		RET

2. 编译时间

不修改源码,动态调整某些内容。比如编译时间、自增版本号等。

// github.com/qyuhen/my; a.go

package my

var buildTime string
$ go build -ldflags "-X github.com/qyuhen/my.buildTime=$(date +'%Y%m%d-%H%M%S')"

3. 类型信息

编译器将类型信息存储到 .rodata 段,以 lea 指令加载。

package main

type data struct {
	x int
}

func main() {
	m := make(map[string]data)
	m["a"] = data{}
}
$ go build -gcflags -S 2>a.txt     # 输出到文件,便于查看。

"".main STEXT

    LEAQ	type.map[string]"".data(SB), AX

type.map[string]"".data SRODATA
    0x0000 08 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00
    0x0010 65 42 fb e0 02 08 08 35 00 00 00 00 00 00 00 00
    0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x0040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x0050 10 08 d0 00 0c 00 00 00                        
    rel 32+8 t=1 runtime.gcbits.01+0
    rel 40+4 t=5 type..namedata.*map[string]main.data-+0
    rel 44+4 t=- type.*map[string]"".data+0
    rel 48+8 t=1 type.string+0
    rel 56+8 t=1 type."".data+0
    rel 64+8 t=1 type.noalg.map.bucket[string]"".data+0
    rel 72+8 t=1 runtime.strhash·f+0

链接器将引用符号( rel )数据( 1 = R_ADDR )填充到上面(十六进制数据) 偏移+长度 位置。

类型( t )参考 src/cmd/internal/objabi/reloctype.go

数据段( STEXT , SRODATA )参考 src/cmd/internal/objabi/symkind.go

Dave Cheney: Go’s hidden #pragmas

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文