2018-08-08

來源:互聯網
上載者:User

go 彙編

編譯一個最簡單的go執行程式

package mainimport  "fmt"func main(){        fmt.Println("helloworld")}

go build -gcflags "-N -l" test.go

使用go tool objdump 反組譯碼

go tool objdump test >test.asm

gdb test

goasm1.png

我們看到彙編的入口地址位於0x452100,開啟test.asm

TEXT _rt0_amd64_linux(SB) /usr/local/go/src/runtime/rt0_linux_amd64.s  rt0_linux_amd64.s:8   0x452100        488d742408      LEAQ 0x8(SP), SI      rt0_linux_amd64.s:9   0x452105        488b3c24        MOVQ 0(SP), DI        rt0_linux_amd64.s:10  0x452109        488d0510000000      LEAQ 0x10(IP), AX     rt0_linux_amd64.s:11  0x452110        ffe0            JMP AX          

可以看到入口為rto_linux_amd64.s (當然了不同平台的入口檔案肯定不一樣),

rto_linux_amd64.s

#include "textflag.h"TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8   LEAQ   8(SP), SI // argv   MOVQ   0(SP), DI // argc   MOVQ   $main(SB), AX   JMP    AX// When building with -buildmode=c-shared, this symbol is called when the shared// library is loaded.// Note: This function calls external C code, which might required 16-byte stack// alignment after cmd/internal/obj applies its transformations.TEXT _rt0_amd64_linux_lib(SB),NOSPLIT,$0x50   MOVQ   SP, AX   ANDQ   $-16, SP   MOVQ   BX, 0x10(SP)   MOVQ   BP, 0x18(SP)   MOVQ   R12, 0x20(SP)   MOVQ   R13, 0x28(SP)   MOVQ   R14, 0x30(SP)   MOVQ   R15, 0x38(SP)   MOVQ   AX, 0x40(SP)   MOVQ   DI, _rt0_amd64_linux_lib_argc<>(SB)   MOVQ   SI, _rt0_amd64_linux_lib_argv<>(SB)   // Synchronous initialization.   MOVQ   $runtime·libpreinit(SB), AX   CALL   AX   // Create a new thread to do the runtime initialization and return.   MOVQ   _cgo_sys_thread_create(SB), AX   TESTQ  AX, AX   JZ nocgo   MOVQ   $_rt0_amd64_linux_lib_go(SB), DI   MOVQ   $0, SI   CALL   AX   JMP    restorenocgo:   MOVQ   $8388608, 0(SP)                    // stacksize   MOVQ   $_rt0_amd64_linux_lib_go(SB), AX   MOVQ   AX, 8(SP)                          // fn   MOVQ   $runtime·newosproc0(SB), AX   CALL   AXrestore:   MOVQ   0x10(SP), BX   MOVQ   0x18(SP), BP   MOVQ   0x20(SP), R12   MOVQ   0x28(SP), R13   MOVQ   0x30(SP), R14   MOVQ   0x38(SP), R15   MOVQ   0x40(SP), SP   RETTEXT _rt0_amd64_linux_lib_go(SB),NOSPLIT,$0   MOVQ   _rt0_amd64_linux_lib_argc<>(SB), DI   MOVQ   _rt0_amd64_linux_lib_argv<>(SB), SI   MOVQ   $runtime·rt0_go(SB), AX   JMP    AXDATA _rt0_amd64_linux_lib_argc<>(SB)/8, $0GLOBL _rt0_amd64_linux_lib_argc<>(SB),NOPTR, $8DATA _rt0_amd64_linux_lib_argv<>(SB)/8, $0GLOBL _rt0_amd64_linux_lib_argv<>(SB),NOPTR, $8TEXT main(SB),NOSPLIT,$-8   MOVQ   $runtime·rt0_go(SB), AX   JMP    AX

上面的是go1.9.2 的rto_linux_amd64.s 檔案內容.

但是我對彙編完全是半懂,只能半看半猜了,更何況這種go的彙編指令有些以前都沒有看到過.好在有偉大的google,另外gdb裡面的彙編單步調試提供了很多方便。

TEXT rt0amd64_linux(SB),NOSPLIT,$-8   LEAQ   8(SP), SI // argv   MOVQ   0(SP), DI // argc   MOVQ   $main(SB), AX   JMP    AX   TEXT main(SB),NOSPLIT,$-8   MOVQ   $runtime·rt0_go(SB), AX   JMP    AX

這是rto_linux_asm64.s 的前幾行,第4行跳到了main(SB)這裡. main(SB)有跳到了runtime·rt0_go(SB) 但是runtime·rt0_go(SB)在那裡呢。這裡有2種方式可以找到,一種我們可以搜尋runtime 目錄下的所有彙編檔案。另外一種方式是使用gdb的彙編單步調試看它跳到那裡

這是使用gdb單步調試的內容,關於gdb彙編單步調試就2指令ni si.

Breakpoint 1, _rt0_amd64_linux () at /usr/local/go/src/runtime/rt0_linux_amd64.s:88               LEAQ    8(SP), SI // argv(gdb) ni9               MOVQ    0(SP), DI // argc(gdb) niBreakpoint 2, _rt0_amd64_linux () at /usr/local/go/src/runtime/rt0_linux_amd64.s:1010              MOVQ    $main(SB), AX(gdb) ni11              JMP     AX(gdb) niStopped due to shared library event(gdb) si74              JMP     AX(gdb) siruntime.rt0_go () at /usr/local/go/src/runtime/asm_amd64.s:1212              MOVQ    DI, AX          // argc(gdb) ni13              MOVQ    SI, BX          // argv(gdb) 

我們看到是跳到了asm_amd64.s:12的12行執行,這裡的代碼我們可以通過旁邊的注釋大概瞭解做了什麼事情

    // create istack out of the given (operating system) stack.    // _cgo_init may update stackguard.    MOVQ    $runtime·g0(SB), DI    LEAQ    (-64*1024+104)(SP), BX    MOVQ    BX, g_stackguard0(DI)    MOVQ    BX, g_stackguard1(DI)    MOVQ    BX, (g_stack+stack_lo)(DI)    MOVQ    SP, (g_stack+stack_hi)(DI)    // find out information about the processor we're on    MOVL    $0, AX    CPUID    MOVL    AX, SI    CMPL    AX, $0    JE  nocpuinfo            MOVL    16(SP), AX      // copy argc    MOVL    AX, 0(SP)    MOVQ    24(SP), AX      // copy argv    MOVQ    AX, 8(SP)    CALL    runtime·args(SB)    CALL    runtime·osinit(SB)    CALL    runtime·schedinit(SB)

主要就是擷取初始化的一些事情,包括runtime.osinit runtime.schedinit 等.

    // 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

這裡把main函數入棧,然後調用newproc建立協程.

小結

這篇主要介紹了使用go tool he gdb簡單的分析golang程式的啟動引導過程,一些細節例如 newproc和mstart 在後面的文章中介紹.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.