• Go程序是如何运行起来的?


    背景

    我们都知道我们执行下面命令会生成一个二进制可执行文件

    但是当我们执行hello时,Go程序是如何执行的呢?

    跟踪

    接下来的工具工具都打包在Docker images里了,大家可以自行实践

    docker pull ngyhd/env:v1

    我们先了解一下Go程序的编译 hello.go 的过程

     上面三幅图

    第一幅是我们程序的代码

    第二幅是执行程序编译

    第三幅是多出了一个可执行的二进制 hello 文件

    什么是可执行文件呢?[1]

     通过entry point 找到Go程序的执行入口,使用readelf 

    以上述为例子,执行了readelf -h ./hello命令 

    我们可以看到ELF Header中的Entry point address 0x45cd80就是程序的入口

    知道了程序入口,那该怎么去跟踪呢?

    dlv调试

    接下来我们使用dlv进行对程序的调试

    第一条红线:dlv exce ./hello 是对hello程序的调式

    第二条红线: b *0x45cd80 是对程序入口进行断点

    第三条红线:是在执行si命令后,程序运行中的代码所在的文件位置 

    根据上图的位置,我们可以知道程序的入口文件是runtime/rt0_linux_amd64.s:8

    我们在GO SDK中可以发现 rt0_linux_amd64 这个文件

    1. #include "textflag.h"
    2. TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8
    3. JMP _rt0_amd64(SB)
    4. TEXT _rt0_amd64_linux_lib(SB),NOSPLIT,$0
    5. JMP _rt0_amd64_lib(SB)

    JMP 在汇编里是跳转的含义,因此执行si(step-instruction)的时候,它会进行跳转

    至此,我们已经找到了Go程序的入口,想分析Go源码,可以学习Go的各种姿势

    dlv更多命令参考 help

    dlv debug main.go #debug一个main.go程序
    break(b)main.main #在main包里的main函数入口打断点
    continue(c) #继续运行,直到断点处停止
    next(n) #单步运行
    locals #打印local variables
    print(p) #打印一个变量或者表达式
    restart(r) #Restart Process
    step-instruction (alias: si)  Single step a single cpu instruction

    References

    1.ELF文件解释

  • 相关阅读:
    DotNetGuide新增C#/.NET/.NET Core充电站(让你学习不迷路)
    Cloud Studio连接MySQL,Access denied for一系列问题
    标注相关的知识点:强制性标准与推荐性标准
    Spring基础——Spring配置Mybatis连接数据库
    【JAVA - List】差集removeAll() 四种方法实现与优化
    智能制造学习记录片和书籍
    求 k 整除最大元素和(dp)
    AI芯片的性能评价
    整型在内存中的存储与管理
    【参营经历贴】2022网安夏令营
  • 原文地址:https://blog.csdn.net/qq_37186127/article/details/125516174