【Golang runtime 学习笔记 - 启动过程分析】
发布于: 2020 年 06 月 20 日
rumtime调试与跟踪
系统环境
[root@jordy tmp]# lsb_release -aLSB Version: :core-4.1-amd64:core-4.1-noarchDistributor ID: CentOSDescription: CentOS Linux release 7.6.1810 (Core) Release: 7.6.1810Codename: 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 versiongo 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 helloGNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-114.el7Copyright (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.pyline 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 filesSymbols 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 *0x44f4d0Breakpoint 1 at 0x44f4d0: file /usr/local/src/golang/go/src/runtime/rt0_linux_amd64.s, line 8.(gdb) runStarting program: /tmp/hello Breakpoint 1, _rt0_amd64_linux () at /usr/local/src/golang/go/src/runtime/rt0_linux_amd64.s:88 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_amd64Breakpoint 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.argsBreakpoint 9 at 0x433fd0: file /usr/local/src/golang/go/src/runtime/runtime1.go, line 60.(gdb) b runtime.osinitBreakpoint 11 at 0x424220: file /usr/local/src/golang/go/src/runtime/os_linux.go, line 272.(gdb) b runtime.schedinitNote: 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 日阅读数: 217
版权声明: 本文为 InfoQ 作者【卓丁】的原创文章。
原文链接:【http://xie.infoq.cn/article/7baab69fe385d0c6a1b35fa32】。文章转载请联系作者。
卓丁
关注
鸟过无痕 2017.12.10 加入
泰戈尔:虽然天空没有留下我的痕迹,但我已飞过。
评论