Golang探索之旅-GMP(一)gdb实践启动过程

408 阅读2分钟

启动

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,真实情况如下:

image.png

启动流程图

graph TD
Start --> Stop