1,编译好的可执行文件的执行入口不是main.main函数,因为编译器会插入一段引导代码,完成诸如命令行参数,运行时初始化等工作,然后才会进入用户逻辑
2,实例代码:
package main
import ("fmt")
func main(){
fmt.Println("hello world")
}
3,编译,然后用GDB查看:
go build -gcflags "-N -l" -o test test.go
4,使用gdb查看 test 文件,info files 查看详细信息
gdb test
(gdb)info files
5,利用断点文件找到目标文件信息
(gdb) b*0x452060
Breakpoint 1 at 0x452060: file /usr/local/go/src/runtime/rt0_linux_amd64.s, line 8.
6,打开rt0_linux_admin64.s 查看第8行,结果如果,可以追溯到rt0_go(SB)
TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8
8 LEAQ 8(SP), SI // argv
9 MOVQ 0(SP), DI // argc
10 MOVQ $main(SB), AX
11 JMP AX
TEXT main(SB),NOSPLIT,$-8
73 MOVQ $runtime·rt0_go(SB), AX
74 JMP AX
7,用GDB设置断点,查看rt0_go所在位置
(gdb) b runtime.rt0_go
Breakpoint 2 at 0x44e850: file /usr/local/go/src/runtime/asm_amd64.s, line 12.
8,查看asm_admin64.s内容
//调用初始化函数
CALL runtime·args(SB)
CALL runtime·osinit(SB)
CALL runtime·schedinit(SB)
// create a new goroutine to start program
MOVQ $runtime·mainPC(SB), AX // entry
PUSHQ AX
PUSHQ $0 // arg size
CALL runtime·newproc(SB)
POPQ AX
POPQ AX
// start this M
CALL runtime·mstart(SB)
9,由汇编语言针对特定平台实现的引导过程全部完成,后续的内容基本上都是由go实现的。
(gdb) b runtime.main
Breakpoint 3 at 0x428810: file /usr/local/go/src/runtime/proc.go, line 106.