启动
0. OS、ENV
[user@ecs ~]# cat /proc/version
Linux version 3.10.0-693.2.2.el7.x86_64 (builder@kbuilder.dev.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC) ) #1 SMP Tue Sep 12 22:26:13 UTC 2017
[user@ecs ~]# go env
GOARCH="amd64"
GOOS="linux"
GOPATH="/root/go"
GOROOT="/data/qsc/go"
...
1. 源码
[user@ecs go-demo]# pwd
/root/go/src/go-demo
[user@ecs go-demo]# touch main.go
[user@ecs go-demo]# vim main.go
package main
import "fmt"
func main() {
fmt.Println("hello world")
}
2. 编译
go build main.go
3. 查看权限
[user@ecs go-demo]# ll
total 1956
-rwxr-xr-x 1 root root 1997487 Sep 22 11:32 main
-rw-r--r-- 1 root root 72 Sep 22 11:32 main.go
4. gdb调试(gdb传送门)
4.1 入口
gdb参数:
info files: b: n:全称next,是单步步过(step over),遇到函数直接跳过,不进入函数内部。
[user@ecs tmp]# gdb main
(gdb) info files
Symbols from "/root/go/src/go-demo/main".
Local exec file:
`/root/go/src/go-demo/main', file type elf64-x86-64.
Entry point: 0x452890
...
(gdb) b *0x452890
Breakpoint 2 at 0x452890: file /data/qsc/go/src/runtime/rt0_linux_amd64.s, line 8.
(gdb) start
Temporary breakpoint 3 at 0x487170: file /root/go/src/go-demo/main.go, line 5.
Starting program: /root/go/src/go-demo/main
Breakpoint 2, _rt0_amd64_linux () at /data/qsc/go/src/runtime/rt0_linux_amd64.s:8
8 JMP _rt0_amd64(SB)
4.2 _rt0_amd64
(gdb) n
_rt0_amd64 () at /data/qsc/go/src/runtime/asm_amd64.s:15
15 MOVQ 0(SP), DI // argc
16 LEAQ 8(SP), SI // argv
17 JMP runtime·rt0_go(SB)
4.3 runtime.rt0_go
(gdb) n
runtime.rt0_go () at /data/qsc/go/src/runtime/asm_amd64.s:89
89 MOVQ DI, AX // argc
90 MOVQ SI, BX // argv
91 SUBQ $(4*8+7), SP // 2args 2auto
92 ANDQ $~15, SP
93 MOVQ AX, 16(SP)
94 MOVQ BX, 24(SP)
4.3.1 初始化g0
(gdb) n
98 MOVQ $runtime·g0(SB), DI
99 LEAQ (-64*1024+104)(SP), BX
100 MOVQ BX, g_stackguard0(DI)
101 MOVQ BX, g_stackguard1(DI)
102 MOVQ BX, (g_stack+stack_lo)(DI)
103 MOVQ SP, (g_stack+stack_hi)(DI)
4.3.2
(gdb) n
106 MOVL $0, AX
107 CPUID
109 CMPL AX, $0
110 JE nocpuinfo
4.3.3
(gdb) n
115 CMPL BX, $0x756E6547 // "Genu"
116 JNE notintel
117 CMPL DX, $0x49656E69 // "ineI"
118 JNE notintel
119 CMPL CX, $0x6C65746E // "ntel"
120 JNE notintel
121 MOVB $1, runtime·isIntel(SB)
122 MOVB $1, runtime·lfenceBeforeRdtsc(SB)
126 MOVL $1, AX
127 CPUID
132 MOVQ _cgo_init(SB), AX
133 TESTQ AX, AX
134 JZ needtls
4.3.4 m0
(gdb) n
164 LEAQ runtime·m0+m_tls(SB), DI
165 CALL runtime·settls(SB)
169 MOVQ $0x123, g(BX)
170 MOVQ runtime·m0+m_tls(SB), AX
171 CMPQ AX, $0x123
172 JEQ 2(PC)
4.3.4 g0关联m0
(gdb) n
177 LEAQ runtime·g0(SB), CX
178 MOVQ CX, g(BX)
179 LEAQ runtime·m0(SB), AX
182 MOVQ CX, m_g0(AX)
184 MOVQ AX, g_m(CX)
4.3.5
(gdb) n
186 CLD // convention is D is always left cleared
187 CALL runtime·check(SB)
4.3.6 init()
(gdb) n
189 MOVL 16(SP), AX // copy argc
190 MOVL AX, 0(SP)
191 MOVQ 24(SP), AX // copy argv
192 MOVQ AX, 8(SP)
193 CALL runtime·args(SB)
194 CALL runtime·osinit(SB)
195 CALL runtime·schedinit(SB)
4.3.6 创建goroutine
(gdb) n
198 MOVQ $runtime·mainPC(SB), AX // entry
199 PUSHQ AX
200 PUSHQ $0 // arg size
201 CALL runtime·newproc(SB)
202 POPQ AX
203 POPQ AX
206 CALL runtime·mstart(SB)
4.3.7 执行main.main()
(gdb) n
Temporary breakpoint 3, main.main () at /root/go/src/go-demo/main.go:5
5 func main() {
6 fmt.Println("hello world")
hello world
4.3.8 回到runtime.main()
runtime.main () at /data/qsc/go/src/runtime/proc.go:209
209 if atomic.Load(&runningPanicDefers) != 0 {
218 if atomic.Load(&panicking) != 0 {
222 exit(0)
[LWP 17700 exited]
[Inferior 1 (process 17700) exited normally]
PS:行与行之间省略了 (gdb) n,真实情况如下:
启动流程图
graph TD
Start --> Stop