【Golang runtime 学习笔记 - 启动过程分析】

用户头像
卓丁
关注
发布于: 2020 年 06 月 20 日
【Golang runtime学习笔记-启动过程分析】

rumtime调试与跟踪

  • 系统环境



[root@jordy tmp]# lsb_release -a
LSB Version: :core-4.1-amd64:core-4.1-noarch
Distributor ID: CentOS
Description: CentOS Linux release 7.6.1810 (Core)
Release: 7.6.1810
Codename: Core
[root@jordy tmp]#
[root@jordy tmp]# uname -a
Linux jordy 3.10.0-957.21.3.el7.x86_64 #1 SMP Tue Jun 18 16:35:19 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
[root@jordy tmp]#
[root@jordy tmp]# go version
go version go1.10.2 linux/amd64



  • 首先准备一个简单的源码文件hello.go

package main
import (
"fmt"
)
func main() {
fmt.Println("hello world")
}



  • go build编译源文件生成可执行文件

go build -gcflags "-N -l " -o hello hello.go
// -N 选项是禁止编译器优化(disable optimizations)
// -l 选项是禁止内联(disable inlining )
//编译器更多选项,可参考帮助文档 (go tool compile --help)



  • 试运行

./hello
hello world
  • 下面我们用gdb来逐步调试与分析可执行程序hello,以揭开golang 程序执行入口的本质与runtime精髓.

[root@jordy tmp]# gdb hello
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-114.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /tmp/hello...done.
warning: File "/usr/local/src/golang/go/src/runtime/runtime-gdb.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load:/usr/bin/mono-gdb.py".
To enable execution of this file add
add-auto-load-safe-path /usr/local/src/golang/go/src/runtime/runtime-gdb.py
line to your configuration file "/root/.gdbinit".
To completely disable this security protection add
set auto-load safe-path /
line to your configuration file "/root/.gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual. E.g., run from the shell:
info "(gdb)Auto-loading safe path"
(gdb) info files
Symbols from "/tmp/hello".
Local exec file:
`/tmp/hello', file type elf64-x86-64.
Entry point: 0x44f4d0
0x0000000000401000 - 0x0000000000482178 is .text
0x0000000000483000 - 0x00000000004c4a7a is .rodata
0x00000000004c4ba0 - 0x00000000004c56e8 is .typelink
0x00000000004c56e8 - 0x00000000004c5728 is .itablink
0x00000000004c5728 - 0x00000000004c5728 is .gosymtab
0x00000000004c5740 - 0x0000000000513a3d is .gopclntab
0x0000000000514000 - 0x0000000000520bdc is .noptrdata
0x0000000000520be0 - 0x00000000005276f0 is .data
0x0000000000527700 - 0x0000000000543d88 is .bss
0x0000000000543da0 - 0x0000000000546438 is .noptrbss
0x0000000000400f9c - 0x0000000000401000 is .note.go.buildid
(gdb)

看到程序的入口地址为0x44f4d0,可以在此地址出打断点:
(gdb) b *0x44f4d0
Breakpoint 1 at 0x44f4d0: file /usr/local/src/golang/go/src/runtime/rt0_linux_amd64.s, line 8.
(gdb) run
Starting program: /tmp/hello

Breakpoint 1, _rt0_amd64_linux () at /usr/local/src/golang/go/src/runtime/rt0_linux_amd64.s:8
8 JMP _rt0_amd64(SB)

首先,go 可执行首先执行的是一个汇编程序rt0_linux_amd64.s,在源码子目录/usr/local/src/golang/go/src/runtime/中,
我们进一步看到,在该目录下go 支持了不同的操作系统,比如有linux,windows,darwin,solaris,plan9,android等等。
针对每种系统,对应一个汇编文件.s


可以在控制台直接运行 go tool dist list 来查看



  • 查看入口文件并跟踪逻辑

在以上,我们初步定位并找到了当前系统(linux 64)所对应的入口文件rt0_linux_amd64.s,该文件源码见下:
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 #include "textflag.h"
6
7 TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8
8 JMP _rt0_amd64(SB)//此行为第8行
9
10 TEXT _rt0_amd64_linux_lib(SB),NOSPLIT,$0
11 JMP _rt0_amd64_lib(SB)

我们看到,在第8行程序无条件跳转并调用了_rt0_amd64函数;
JMP 指令是无条件跳转的意思,具体可参考go汇编的资料,如
https://xargin.com/plan9-assembly/

rt0_amd64函数在那? 可以继续设置断点查看:
(gdb) b _rt0_amd64
Breakpoint 2 at 0x44be00: file /usr/local/src/golang/go/src/runtime/asm_amd64.s, line 15.
(gdb)

我们看到_rt0_amd64在asm_amd64.s 中定义,如
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 #include "go_asm.h"
6 #include "go_tls.h"
7 #include "funcdata.h"
8 #include "textflag.h"
9
10 // _rt0_amd64 is common startup code for most amd64 systems when using
11 // internal linking. This is the entry point for the program from the
12 // kernel for an ordinary -buildmode=exe program. The stack holds the
13 // number of arguments and the C-style argv.
14 TEXT _rt0_amd64(SB),NOSPLIT,$-8
15 MOVQ 0(SP), DI // argc
16 LEAQ 8(SP), SI // argv
17 JMP runtime·rt0_go(SB)
18

看注释信息:当使用内部链接时,_rt0_amd64是大多数amd64系统的常用启动代码,
证明这是一个共用的封装,几乎大部分的64位系统都调用此封装;
看到在_rt0_amd64中,代码逻辑进一步无条件跳转到了 runtime·rt0_go函数, runtime·rt0_go在哪?继续打断点跟踪:

//注意要将·换成.
(gdb) b runtime.rt0_go
Breakpoint 3 at 0x44be10: file /usr/local/src/golang/go/src/runtime/asm_amd64.s, line 89.

看到rt0_go定义位于asm_amd64.s文件的约89行,好戏才刚刚开始,对于asm_amd64.s文件
我们逐步跟踪:rt0_go->nocpuinfo->ok
看到在ok 块中调用了几个核心步骤,正是在该块中,完成了初始化和运行时的核心步骤

231 ok:
232 // set the per-goroutine and per-mach "registers"
233 get_tls(BX)
234 LEAQ runtime·g0(SB), CX
235 MOVQ CX, g(BX)
236 LEAQ runtime·m0(SB), AX
237
238 // save m->g0 = g0
239 MOVQ CX, m_g0(AX)
240 // save m0 to g0->m
241 MOVQ AX, g_m(CX)
242
243 CLD // convention is D is always left cleared
244 CALL runtime·check(SB)
245
246 MOVL 16(SP), AX // copy argc
247 MOVL AX, 0(SP)
248 MOVQ 24(SP), AX // copy argv
249 MOVQ AX, 8(SP)
250 CALL runtime·args(SB)
251 CALL runtime·osinit(SB)
252 CALL runtime·schedinit(SB)
253
254 // create a new goroutine to start program
255 MOVQ $runtime·mainPC(SB), AX // entry
256 PUSHQ AX
257 PUSHQ $0 // arg size
258 CALL runtime·newproc(SB)
259 POPQ AX
260 POPQ AX
261
262 // start this M
263 CALL runtime·mstart(SB)
264
265 MOVL $0xf1, 0xf1 // crash
266 RET
267
268 DATA runtime·mainPC+0(SB)/8,$runtime·main(SB)
269 GLOBL runtime·mainPC(SB),RODATA,$8

初步看到,初始化过程陆续调用了几个关键的函数,如:
runtime·args(SB),runtime·osinit(SB),runtime·schedinit(SB),runtime·mainPC(SB),runtime·newproc(SB),runtime·mstart(SB),runtime·main(SB)

可以清晰地看到,在执行咱们的main.main之前,运行时进行了多个其他的步骤以完成初始化工作,即得出结论:
main.main并不是go 可执行的入口!
下面我们来专门的分析初始化的过程,了解golang runtime启动时的精髓.




runtime 初始化过程分析

(gdb) b runtime.args
Breakpoint 9 at 0x433fd0: file /usr/local/src/golang/go/src/runtime/runtime1.go, line 60.

(gdb) b runtime.osinit
Breakpoint 11 at 0x424220: file /usr/local/src/golang/go/src/runtime/os_linux.go, line 272.

(gdb) b runtime.schedinit
Note: breakpoints 8 and 12 also set at pc 0x4288b0.
Breakpoint 13 at 0x4288b0: file /usr/local/src/golang/go/src/runtime/proc.go, line 477.




proc.go

// The bootstrap sequence is:
//
// call osinit
// call schedinit
// make & queue new G
// call runtime·mstart
//
// The new G calls runtime·main.
func schedinit() {
// raceinit must be the first call to race detector.
// In particular, it must be done before mallocinit below calls racemapshadow.
_g_ := getg()
if raceenabled {
_g_.racectx, raceprocctx0 = raceinit()
}
sched.maxmcount = 10000
tracebackinit()
moduledataverify()
stackinit()
mallocinit()
mcommoninit(_g_.m)
alginit() // maps must not be used before this call
modulesinit() // provides activeModules
typelinksinit() // uses maps, activeModules
itabsinit() // uses activeModules
msigsave(_g_.m)
initSigmask = _g_.m.sigmask
goargs()
goenvs()
parsedebugvars()
gcinit()
sched.lastpoll = uint64(nanotime())
procs := ncpu
if n, ok := atoi32(gogetenv("GOMAXPROCS")); ok && n > 0 {
procs = n
}
if procresize(procs) != nil {
throw("unknown runnable goroutine during bootstrap")
}
// For cgocheck > 1, we turn on the write barrier at all times
// and check all pointer writes. We can't do this until after
// procresize because the write barrier needs a P.
if debug.cgocheck > 1 {
writeBarrier.cgo = true
writeBarrier.enabled = true
for _, p := range allp {
p.wbBuf.reset()
}
}
if buildVersion == "" {
// Condition should never trigger. This code just serves
// to ensure runtime·buildVersion is kept in the resulting binary.
buildVersion = "unknown"
}
}



runtime.main 定义在proc.go

// The main goroutine.
func main() {
g := getg()
// Racectx of m0->g0 is used only as the parent of the main goroutine.
// It must not be used for anything else.
g.m.g0.racectx = 0
// Max stack size is 1 GB on 64-bit, 250 MB on 32-bit.
// Using decimal instead of binary GB and MB because
// they look nicer in the stack overflow failure message.
if sys.PtrSize == 8 {
maxstacksize = 1000000000
} else {
maxstacksize = 250000000
}
// Allow newproc to start new Ms.
mainStarted = true
systemstack(func() {
newm(sysmon, nil)
})
// Lock the main goroutine onto this, the main OS thread,
// during initialization. Most programs won't care, but a few
// do require certain calls to be made by the main thread.
// Those can arrange for main.main to run in the main thread
// by calling runtime.LockOSThread during initialization
// to preserve the lock.
lockOSThread()
if g.m != &m0 {
throw("runtime.main not on m0")
}
//启动runtime包内所有初始化函数init
runtime_init() // must be before defer
if nanotime() == 0 {
throw("nanotime returning zero")
}
// Defer unlock so that runtime.Goexit during init does the unlock too.
needUnlock := true
defer func() {
if needUnlock {
unlockOSThread()
}
}()
// Record when the world started. Must be after runtime_init
// because nanotime on some platforms depends on startNano.
runtimeInitTime = nanotime()
//启动垃圾回收器后台操作
gcenable()
main_init_done = make(chan bool)
if iscgo {
if _cgo_thread_start == nil {
throw("_cgo_thread_start missing")
}
if GOOS != "windows" {
if _cgo_setenv == nil {
throw("_cgo_setenv missing")
}
if _cgo_unsetenv == nil {
throw("_cgo_unsetenv missing")
}
}
if _cgo_notify_runtime_init_done == nil {
throw("_cgo_notify_runtime_init_done missing")
}
// Start the template thread in case we enter Go from
// a C-created thread and need to create a new thread.
startTemplateThread()
cgocall(_cgo_notify_runtime_init_done, nil)
}
//启动所有的用户包初始化逻辑
fn := main_init // make an indirect call, as the linker doesn't know the address of the main package when laying down the runtime
fn()
close(main_init_done)
needUnlock = false
unlockOSThread()
if isarchive || islibrary {
// A program compiled with -buildmode=c-archive or c-shared
// has a main, but it is not executed.
return
}
//执行用户逻辑的入口,即咱们自己的main函数
fn = main_main // make an indirect call, as the linker doesn't know the address of the main package when laying down the runtime
fn()
if raceenabled {
racefini()
}
// Make racy client program work: if panicking on
// another goroutine at the same time as main returns,
// let the other goroutine finish printing the panic trace.
// Once it does, it will exit. See issues 3934 and 20018.
if atomic.Load(&runningPanicDefers) != 0 {
// Running deferred functions should not take long.
for c := 0; c < 1000; c++ {
if atomic.Load(&runningPanicDefers) == 0 {
break
}
Gosched()
}
}
if atomic.Load(&panicking) != 0 {
gopark(nil, nil, "panicwait", traceEvGoStop, 1)
}
exit(0)
for {
var x *int32
*x = 0
}
}

代码我们来透析init的顺序



sym/lib/sum.go

package lib
func init() {
println("sum.init")
}
func Sum(x ...int) int {
n := 0
for _, i := range x {
n += i
}
return n
}

sym/main.go

package main
import (
_ "net/http"
)
func init() {
println("main.init.2")
}
func main() {
test()
}
func init() {
println("main.init.1")
}

sym/test.go



package main
import "sym/lib"
func init() {
println("test.init")
}
func test() {
println(lib.Sum(1, 2, 3))
}



TEXT runtime.init.0(SB) /usr/local/src/golang/go/src/runtime/cpuflags_amd64.go
cpuflags_amd64.go:11 0x406480 8b0596083d00 MOVL runtime.processorVersionInfo(SB), AX
cpuflags_amd64.go:11 0x406486 25f03fff0f ANDL $0xfff3ff0, AX
cpuflags_amd64.go:13 0x40648b 0fb60d1e083d00 MOVZX runtime.isIntel(SB), CX
cpuflags_amd64.go:13 0x406492 84c9 TESTL CL, CL
cpuflags_amd64.go:13 0x406494 7425 JE 0x4064bb
cpuflags_amd64.go:14 0x406496 3da0060200 CMPL $0x206a0, AX
cpuflags_amd64.go:14 0x40649b 751e JNE 0x4064bb
cpuflags_amd64.go:14 0x40649d b801000000 MOVL $0x1, AX
cpuflags_amd64.go:19 0x4064a2 0fb60d0e083d00 MOVZX runtime.support_avx(SB), CX
cpuflags_amd64.go:19 0x4064a9 84c9 TESTL CL, CL
cpuflags_amd64.go:19 0x4064ab 740a JE 0x4064b7
cpuflags_amd64.go:19 0x4064ad 83f001 XORL $0x1, AX
cpuflags_amd64.go:19 0x4064b0 88050c083d00 MOVB AL, runtime.useAVXmemmove(SB)
cpuflags_amd64.go:20 0x4064b6 c3 RET
cpuflags_amd64.go:20 0x4064b7 31c0 XORL AX, AX
cpuflags_amd64.go:19 0x4064b9 ebf5 JMP 0x4064b0
cpuflags_amd64.go:15 0x4064bb 3dd0060200 CMPL $0x206d0, AX
cpuflags_amd64.go:15 0x4064c0 7507 JNE 0x4064c9
cpuflags_amd64.go:15 0x4064c2 b801000000 MOVL $0x1, AX
cpuflags_amd64.go:15 0x4064c7 ebd9 JMP 0x4064a2
cpuflags_amd64.go:16 0x4064c9 3da0060300 CMPL $0x306a0, AX
cpuflags_amd64.go:16 0x4064ce 7507 JNE 0x4064d7
cpuflags_amd64.go:16 0x4064d0 b801000000 MOVL $0x1, AX
cpuflags_amd64.go:16 0x4064d5 ebcb JMP 0x4064a2
cpuflags_amd64.go:17 0x4064d7 3de0060300 CMPL $0x306e0, AX
cpuflags_amd64.go:17 0x4064dc 0f94c0 SETE AL
cpuflags_amd64.go:17 0x4064df ebc1 JMP 0x4064a2

TEXT runtime.init.1(SB) /usr/local/src/golang/go/src/runtime/mgcwork.go
mgcwork.go:25 0x420730 c3 RET

TEXT runtime.init.2(SB) /usr/local/src/golang/go/src/runtime/mstats.go
mstats.go:438 0x425fa0 64488b0c25f8ffffff MOVQ FS:0xfffffff8, CX
mstats.go:438 0x425fa9 488b7110 MOVQ 0x10(CX), SI
mstats.go:438 0x425fad 4881fedefaffff CMPQ $-0x522, SI
mstats.go:438 0x425fb4 0f84a9000000 JE 0x426063
mstats.go:438 0x425fba 488d842470030000 LEAQ 0x370(SP), AX
mstats.go:438 0x425fc2 4829f0 SUBQ SI, AX
mstats.go:438 0x425fc5 483d98190000 CMPQ $0x1998, AX
mstats.go:438 0x425fcb 0f8692000000 JBE 0x426063
mstats.go:438 0x425fd1 4881eca8160000 SUBQ $0x16a8, SP
mstats.go:438 0x425fd8 4889ac24a0160000 MOVQ BP, 0x16a0(SP)
mstats.go:438 0x425fe0 488dac24a0160000 LEAQ 0x16a0(SP), BP
mstats.go:439 0x425fe8 488d7c2410 LEAQ 0x10(SP), DI
mstats.go:439 0x425fed b9d2020000 MOVL $0x2d2, CX
mstats.go:439 0x425ff2 31c0 XORL AX, AX
mstats.go:439 0x425ff4 f348ab REP; STOSQ AX, ES:0(DI)
mstats.go:440 0x425ff7 488b15cae33500 MOVQ runtime.sizeof_C_MStats(SB), DX
mstats.go:440 0x425ffe 4881fa90160000 CMPQ $0x1690, DX
mstats.go:440 0x426005 7510 JNE 0x426017
mstats.go:440 0x426007 488bac24a0160000 MOVQ 0x16a0(SP), BP
mstats.go:440 0x42600f 4881c4a8160000 ADDQ $0x16a8, SP
mstats.go:440 0x426016 c3 RET
mstats.go:441 0x426017 e8944d0000 CALL runtime.printlock(SB)
mstats.go:441 0x42601c 488b05a5e33500 MOVQ runtime.sizeof_C_MStats(SB), AX
mstats.go:441 0x426023 48890424 MOVQ AX, 0(SP)
mstats.go:441 0x426027 e8f4530000 CALL runtime.printuint(SB)
mstats.go:441 0x42602c e8bf4f0000 CALL runtime.printsp(SB)
mstats.go:441 0x426031 48c7042490160000 MOVQ $0x1690, 0(SP)
mstats.go:441 0x426039 e8e2530000 CALL runtime.printuint(SB)
mstats.go:441 0x42603e e8fd4f0000 CALL runtime.printnl(SB)
mstats.go:441 0x426043 e8e84d0000 CALL runtime.printunlock(SB)
mstats.go:442 0x426048 488d0596892400 LEAQ 0x248996(IP), AX
mstats.go:442 0x42604f 48890424 MOVQ AX, 0(SP)
mstats.go:442 0x426053 48c744240824000000 MOVQ $0x24, 0x8(SP)
mstats.go:442 0x42605c e81f440000 CALL runtime.throw(SB)
mstats.go:442 0x426061 0f0b UD2
mstats.go:438 0x426063 e888d00200 CALL runtime.morestack_noctxt(SB)
mstats.go:438 0x426068 e933ffffff JMP runtime.init.2(SB)

TEXT runtime.init.3(SB) /usr/local/src/golang/go/src/runtime/panic.go
panic.go:180 0x429310 64488b0c25f8ffffff MOVQ FS:0xfffffff8, CX
panic.go:180 0x429319 483b6110 CMPQ 0x10(CX), SP
panic.go:180 0x42931d 765d JBE 0x42937c
panic.go:180 0x42931f 4883ec18 SUBQ $0x18, SP
panic.go:180 0x429323 48896c2410 MOVQ BP, 0x10(SP)
panic.go:180 0x429328 488d6c2410 LEAQ 0x10(SP), BP
panic.go:181 0x42932d 0f57c0 XORPS X0, X0
panic.go:181 0x429330 0f110424 MOVUPS X0, 0(SP)
panic.go:182 0x429334 488b0d95942600 MOVQ runtime.statictmp_20(SB), CX
panic.go:182 0x42933b 488d15de9d1d00 LEAQ 0x1d9dde(IP), DX
panic.go:182 0x429342 48891424 MOVQ DX, 0(SP)
panic.go:182 0x429346 48894c2408 MOVQ CX, 0x8(SP)
panic.go:183 0x42934b 488b0c24 MOVQ 0(SP), CX
panic.go:183 0x42934f 8b154bdc3a00 MOVL runtime.writeBarrier(SB), DX
panic.go:183 0x429355 488b4130 MOVQ 0x30(CX), AX
panic.go:183 0x429359 85d2 TESTL DX, DX
panic.go:183 0x42935b 7511 JNE 0x42936e
panic.go:183 0x42935d 488905dcef3800 MOVQ AX, runtime.deferType(SB)
panic.go:184 0x429364 488b6c2410 MOVQ 0x10(SP), BP
panic.go:184 0x429369 4883c418 ADDQ $0x18, SP
panic.go:184 0x42936d c3 RET
panic.go:183 0x42936e 488d3dcbef3800 LEAQ runtime.deferType(SB), DI
panic.go:183 0x429375 e876c70200 CALL runtime.gcWriteBarrier(SB)
panic.go:183 0x42937a ebe8 JMP 0x429364
panic.go:180 0x42937c e86f9d0200 CALL runtime.morestack_noctxt(SB)
panic.go:180 0x429381 eb8d JMP runtime.init.3(SB)

TEXT runtime.init.4(SB) /usr/local/src/golang/go/src/runtime/proc.go
proc.go:236 0x42bef0 64488b0c25f8ffffff MOVQ FS:0xfffffff8, CX
proc.go:236 0x42bef9 483b6110 CMPQ 0x10(CX), SP
proc.go:236 0x42befd 7630 JBE 0x42bf2f
proc.go:236 0x42beff 4883ec18 SUBQ $0x18, SP
proc.go:236 0x42bf03 48896c2410 MOVQ BP, 0x10(SP)
proc.go:236 0x42bf08 488d6c2410 LEAQ 0x10(SP), BP
proc.go:237 0x42bf0d c7042400000000 MOVL $0x0, 0(SP)
proc.go:237 0x42bf14 488d053dc32400 LEAQ 0x24c33d(IP), AX
proc.go:237 0x42bf1b 4889442408 MOVQ AX, 0x8(SP)
proc.go:237 0x42bf20 e8bb770000 CALL runtime.newproc(SB)
proc.go:238 0x42bf25 488b6c2410 MOVQ 0x10(SP), BP
proc.go:238 0x42bf2a 4883c418 ADDQ $0x18, SP
proc.go:238 0x42bf2e c3 RET
proc.go:236 0x42bf2f e8bc710200 CALL runtime.morestack_noctxt(SB)
proc.go:236 0x42bf34 ebba JMP runtime.init.4(SB)

TEXT runtime.init.5(SB) /usr/local/src/golang/go/src/runtime/signal_unix.go
signal_unix.go:64 0x43e320 c3 RET

TEXT runtime.init(SB) <autogenerated>
<autogenerated>:1 0x452a70 64488b0c25f8ffffff MOVQ FS:0xfffffff8, CX
<autogenerated>:1 0x452a79 483b6110 CMPQ 0x10(CX), SP
<autogenerated>:1 0x452a7d 0f86e6000000 JBE 0x452b69
<autogenerated>:1 0x452a83 4883ec20 SUBQ $0x20, SP
<autogenerated>:1 0x452a87 48896c2418 MOVQ BP, 0x18(SP)
<autogenerated>:1 0x452a8c 488d6c2418 LEAQ 0x18(SP), BP
<autogenerated>:1 0x452a91 0fb60517423800 MOVZX runtime.initdone.(SB), AX
<autogenerated>:1 0x452a98 3c01 CMPL $0x1, AL
<autogenerated>:1 0x452a9a 760a JBE 0x452aa6
<autogenerated>:1 0x452a9c 488b6c2418 MOVQ 0x18(SP), BP
<autogenerated>:1 0x452aa1 4883c420 ADDQ $0x20, SP
<autogenerated>:1 0x452aa5 c3 RET
<autogenerated>:1 0x452aa6 7507 JNE 0x452aaf
<autogenerated>:1 0x452aa8 e8a364fdff CALL runtime.throwinit(SB)
<autogenerated>:1 0x452aad 0f0b UD2
<autogenerated>:1 0x452aaf c605f941380001 MOVB $0x1, runtime.initdone.(SB)
float.go:9 0x452ab6 48b8000000000000f07f MOVQ $0x7ff0000000000000, AX
float.go:9 0x452ac0 48890424 MOVQ AX, 0(SP)
float.go:9 0x452ac4 e86753fbff CALL runtime.float64frombits(SB)
float.go:9 0x452ac9 f20f10442408 MOVSD_XMM 0x8(SP), X0
float.go:9 0x452acf f20f1105f1423800 MOVSD_XMM X0, runtime.inf(SB)
select.go:48 0x452ad7 488d05c2bf1c00 LEAQ 0x1cbfc2(IP), AX
select.go:48 0x452ade 48890424 MOVQ AX, 0(SP)
select.go:48 0x452ae2 488d0507572200 LEAQ 0x225707(IP), AX
select.go:48 0x452ae9 4889442408 MOVQ AX, 0x8(SP)
select.go:48 0x452aee e84d9ffdff CALL runtime.funcPC(SB)
select.go:48 0x452af3 488b442410 MOVQ 0x10(SP), AX
select.go:48 0x452af8 48890599423800 MOVQ AX, runtime.chansendpc(SB)
select.go:49 0x452aff 488d053abf1c00 LEAQ 0x1cbf3a(IP), AX
select.go:49 0x452b06 48890424 MOVQ AX, 0(SP)
select.go:49 0x452b0a 488d05d7562200 LEAQ 0x2256d7(IP), AX
select.go:49 0x452b11 4889442408 MOVQ AX, 0x8(SP)
select.go:49 0x452b16 e8259ffdff CALL runtime.funcPC(SB)
select.go:49 0x452b1b 488b442410 MOVQ 0x10(SP), AX
select.go:49 0x452b20 48890569423800 MOVQ AX, runtime.chanrecvpc(SB)
time.go:405 0x452b27 e854410000 CALL runtime.nanotime(SB)
time.go:405 0x452b2c 488b0424 MOVQ 0(SP), AX
time.go:405 0x452b30 48ffc8 DECQ AX
time.go:405 0x452b33 488905f6423800 MOVQ AX, runtime.startNano(SB)
<autogenerated>:1 0x452b3a e84139fbff CALL runtime.init.0(SB)
<autogenerated>:1 0x452b3f e8ecdbfcff CALL runtime.init.1(SB)
<autogenerated>:1 0x452b44 e85734fdff CALL runtime.init.2(SB)
<autogenerated>:1 0x452b49 e8c267fdff CALL runtime.init.3(SB)
<autogenerated>:1 0x452b4e e89d93fdff CALL runtime.init.4(SB)
<autogenerated>:1 0x452b53 e8c8b7feff CALL runtime.init.5(SB)
<autogenerated>:1 0x452b58 c6055041380002 MOVB $0x2, runtime.initdone.(SB)
<autogenerated>:1 0x452b5f 488b6c2418 MOVQ 0x18(SP), BP
<autogenerated>:1 0x452b64 4883c420 ADDQ $0x20, SP
<autogenerated>:1 0x452b68 c3 RET
<autogenerated>:1 0x452b69 e882050000 CALL runtime.morestack_noctxt(SB)
<autogenerated>:1 0x452b6e e9fdfeffff JMP runtime.init(SB)





TEXT main.init.0(SB) /root/go/src/sym/main.go
main.go:7 0x5e3720 64488b0c25f8ffffff MOVQ FS:0xfffffff8, CX
main.go:7 0x5e3729 483b6110 CMPQ 0x10(CX), SP
main.go:7 0x5e372d 763b JBE 0x5e376a
main.go:7 0x5e372f 4883ec18 SUBQ $0x18, SP
main.go:7 0x5e3733 48896c2410 MOVQ BP, 0x10(SP)
main.go:7 0x5e3738 488d6c2410 LEAQ 0x10(SP), BP
main.go:8 0x5e373d e86e76e4ff CALL runtime.printlock(SB)
main.go:8 0x5e3742 488d05e4420800 LEAQ 0x842e4(IP), AX
main.go:8 0x5e3749 48890424 MOVQ AX, 0(SP)
main.go:8 0x5e374d 48c74424080c000000 MOVQ $0xc, 0x8(SP)
main.go:8 0x5e3756 e8957fe4ff CALL runtime.printstring(SB)
main.go:8 0x5e375b e8d076e4ff CALL runtime.printunlock(SB)
main.go:9 0x5e3760 488b6c2410 MOVQ 0x10(SP), BP
main.go:9 0x5e3765 4883c418 ADDQ $0x18, SP
main.go:9 0x5e3769 c3 RET
main.go:7 0x5e376a e881f9e6ff CALL runtime.morestack_noctxt(SB)
main.go:7 0x5e376f ebaf JMP main.init.0(SB)

TEXT main.init.1(SB) /root/go/src/sym/main.go
main.go:13 0x5e37b0 64488b0c25f8ffffff MOVQ FS:0xfffffff8, CX
main.go:13 0x5e37b9 483b6110 CMPQ 0x10(CX), SP
main.go:13 0x5e37bd 763b JBE 0x5e37fa
main.go:13 0x5e37bf 4883ec18 SUBQ $0x18, SP
main.go:13 0x5e37c3 48896c2410 MOVQ BP, 0x10(SP)
main.go:13 0x5e37c8 488d6c2410 LEAQ 0x10(SP), BP
main.go:14 0x5e37cd e8de75e4ff CALL runtime.printlock(SB)
main.go:14 0x5e37d2 488d0548420800 LEAQ 0x84248(IP), AX
main.go:14 0x5e37d9 48890424 MOVQ AX, 0(SP)
main.go:14 0x5e37dd 48c74424080c000000 MOVQ $0xc, 0x8(SP)
main.go:14 0x5e37e6 e8057fe4ff CALL runtime.printstring(SB)
main.go:14 0x5e37eb e84076e4ff CALL runtime.printunlock(SB)
main.go:15 0x5e37f0 488b6c2410 MOVQ 0x10(SP), BP
main.go:15 0x5e37f5 4883c418 ADDQ $0x18, SP
main.go:15 0x5e37f9 c3 RET
main.go:13 0x5e37fa e8f1f8e6ff CALL runtime.morestack_noctxt(SB)
main.go:13 0x5e37ff ebaf JMP main.init.1(SB)

TEXT main.init.2(SB) /root/go/src/sym/test.go
test.go:5 0x5e3810 64488b0c25f8ffffff MOVQ FS:0xfffffff8, CX
test.go:5 0x5e3819 483b6110 CMPQ 0x10(CX), SP
test.go:5 0x5e381d 763b JBE 0x5e385a
test.go:5 0x5e381f 4883ec18 SUBQ $0x18, SP
test.go:5 0x5e3823 48896c2410 MOVQ BP, 0x10(SP)
test.go:5 0x5e3828 488d6c2410 LEAQ 0x10(SP), BP
test.go:6 0x5e382d e87e75e4ff CALL runtime.printlock(SB)
test.go:6 0x5e3832 488d051d3b0800 LEAQ 0x83b1d(IP), AX
test.go:6 0x5e3839 48890424 MOVQ AX, 0(SP)
test.go:6 0x5e383d 48c74424080a000000 MOVQ $0xa, 0x8(SP)
test.go:6 0x5e3846 e8a57ee4ff CALL runtime.printstring(SB)
test.go:6 0x5e384b e8e075e4ff CALL runtime.printunlock(SB)
test.go:7 0x5e3850 488b6c2410 MOVQ 0x10(SP), BP
test.go:7 0x5e3855 4883c418 ADDQ $0x18, SP
test.go:7 0x5e3859 c3 RET
test.go:5 0x5e385a e891f8e6ff CALL runtime.morestack_noctxt(SB)
test.go:5 0x5e385f ebaf JMP main.init.2(SB)

TEXT main.init(SB) <autogenerated>
<autogenerated>:1 0x5e3930 64488b0c25f8ffffff MOVQ FS:0xfffffff8, CX
<autogenerated>:1 0x5e3939 483b6110 CMPQ 0x10(CX), SP
<autogenerated>:1 0x5e393d 7666 JBE 0x5e39a5
<autogenerated>:1 0x5e393f 4883ec08 SUBQ $0x8, SP
<autogenerated>:1 0x5e3943 48892c24 MOVQ BP, 0(SP)
<autogenerated>:1 0x5e3947 488d2c24 LEAQ 0(SP), BP
<autogenerated>:1 0x5e394b 0fb6053b331f00 MOVZX main.initdone.(SB), AX
<autogenerated>:1 0x5e3952 3c01 CMPL $0x1, AL
<autogenerated>:1 0x5e3954 7702 JA 0x5e3958
<autogenerated>:1 0x5e3956 eb09 JMP 0x5e3961
<autogenerated>:1 0x5e3958 488b2c24 MOVQ 0(SP), BP
<autogenerated>:1 0x5e395c 4883c408 ADDQ $0x8, SP
<autogenerated>:1 0x5e3960 c3 RET
<autogenerated>:1 0x5e3961 0fb60525331f00 MOVZX main.initdone.(SB), AX
<autogenerated>:1 0x5e3968 3c01 CMPL $0x1, AL
<autogenerated>:1 0x5e396a 7402 JE 0x5e396e
<autogenerated>:1 0x5e396c eb07 JMP 0x5e3975
<autogenerated>:1 0x5e396e e8dd55e4ff CALL runtime.throwinit(SB)
<autogenerated>:1 0x5e3973 0f0b UD2
<autogenerated>:1 0x5e3975 c60511331f0001 MOVB $0x1, main.initdone.(SB)
<autogenerated>:1 0x5e397c e81f63ffff CALL net/http.init(SB)
<autogenerated>:1 0x5e3981 e83afdffff CALL sym/lib.init(SB)
<autogenerated>:1 0x5e3986 e895fdffff CALL main.init.0(SB)
<autogenerated>:1 0x5e398b e820feffff CALL main.init.1(SB)
<autogenerated>:1 0x5e3990 e87bfeffff CALL main.init.2(SB)
<autogenerated>:1 0x5e3995 c605f1321f0002 MOVB $0x2, main.initdone.(SB)
<autogenerated>:1 0x5e399c 488b2c24 MOVQ 0(SP), BP
<autogenerated>:1 0x5e39a0 4883c408 ADDQ $0x8, SP
<autogenerated>:1 0x5e39a4 c3 RET
<autogenerated>:1 0x5e39a5 e846f7e6ff CALL runtime.morestack_noctxt(SB)
<autogenerated>:1 0x5e39aa eb84 JMP main.init(SB)




发布于: 2020 年 06 月 20 日 阅读数: 152
用户头像

卓丁

关注

鸟过无痕 2017.12.10 加入

泰戈尔:虽然天空没有留下我的痕迹,但我已飞过。

评论

发布
暂无评论
【Golang runtime学习笔记-启动过程分析】