Golang源码探索(一) 编译和调试源码(转)
GO可以说是近几年最热门的新兴语言之一了, 一般人看到分布式和大数据就会想到GO,
这个系列的文章会通过研究golang的源代码来分析内部的实现原理,
和CoreCLR不同的是, golang的源代码已经被很多人研究过了, 我将会着重研究他们未提到过的部分.
另一点和CoreCLR不同的是, golang的源代码非常易懂, 注释也非常的丰富,
很明显Google的工程师在写代码的时候有考虑其他人会去看这份代码.
尽管代码非常易懂, 研究它们还是需要实际运行和调试才能得到更好的理解,
这个系列分析的golang源代码是Google官方的实现的1.9.2版本, 不适用于其他版本和gccgo等其他实现,
运行环境是Ubuntu 16.04 LTS 64bit.
编译golang源代码
go的源代码是用go写的, 编译也需要一个可运行的go.
首先我们从官网下载源代码和二进制文件.
go1.9.2.src.tar.gz
go1.9.2.linux-amd64.tar.gz
注意两个压缩包解压出来文件夹名称都是go, 我们解压到以下目录:
源代码: ~/git_go/go_src
二进制: ~/git_go/go_bin

编译go之前需要设置环境变量,GOROOT_BOOTSTRAP是go二进制文件夹的所在目录,GO_GCFLAGS是编译go时使用的参数.
export GOROOT_BOOTSTRAP=~/git_go/go_bin
export GO_GCFLAGS="-N -l"
这里的-N参数代表禁止优化, -l参数代表禁止内联, go在编译目标程序的时候会嵌入运行时(runtime)的二进制,
禁止优化和内联可以让运行时(runtime)中的函数变得更容易调试.
都准备好以后就可以进入go的源代码文件夹执行all.bash编译了:

编译的结果在~/git_go/go_src/bin下:

调试golang源代码
之前CoreCLR的系列中我使用了lldb, 在这个系列中我继续沿用这个调试器.
这个系列中使用的是lldb 4.0.
以以下源代码(hello.go)为例:
package main
import (
"fmt"
"time"
)
func printNumber(from, to int, c chan int) {
for x := from; x <= to; x++ {
fmt.Printf("%d\n", x)
time.Sleep(1 * time.Millisecond)
}
c <- 0
}
func main() {
c := make(chan int, 3)
go printNumber(1, 3, c)
go printNumber(4, 6, c)
_, _ = <- c, <- c
}
编译源代码使用以下命令, 这里的-l参数的意思和上面一样, 如果有需要还可以加-N参数:
~/git_go/go_src/bin/go build -gcflags "-l" hello.go
编译后使用lldb运行:
lldb ./hello

go里面的函数符号名称的命名规则是包名称.函数名称, 例如主函数的符号名称是main.main, 运行时中的newobject的符号名称是runtime.newobject.
首先给主函数下一个断点然后运行:

可以看到成功的进入了主函数, 并且有源代码提示.
接下来给按文件名和行数来下断点:

然后查看函数的汇编代码:

关于lldb的命令可以查看这篇文档.
在我使用的环境中lldb可以正常的下断点, 步进和步过go代码或者汇编指令,
但打印变量输出的值有可能是错的, 即使不开启优化.
虽然打印变量这个功能不好用, 我们仍然可以直接让go输出我们想要的值,
例如修改runtime/malloc.go输出当前环境下arena|spans|bitmap区的大小:

修改后进入src并执行./make.bash, 然后重新编译目标程序, 运行:

可以看到当前环境下arena是512G, spans是512M, bitmap是16G.
这个方法虽然比较笨, 但是可以在任何情况下输出我们想要的值.
此外, go运行时(runtime)的源代码会包括在目标文件中,
例如你对runtime.newobject下断点可以对go自身的源代码进行调试.
参考链接
https://golang.org
https://golang.org/doc/install/source
https://golang.org/doc/gdb
http://lldb.llvm.org/tutorial.html
http://legendtkl.com/archives
接下来我将分析golang的任务调度机制和三色GC的具体实现, 敬请期待.
Golang源码探索(一) 编译和调试源码(转)的更多相关文章
- Golang源码探索(一) 编译和调试源码
GO可以说是近几年最热门的新型语言之一了, 一般人看到分布式和大数据就会想到GO, 这个系列的文章会通过研究golang的源代码来分析内部的实现原理, 和CoreCLR不同的是, golang的源代码 ...
- Android之源码之模块编译和调试
Android之源码之模块编译调试 (一) 进行源码模块修改进行编译的调试 1.首先是从git或者svn上拉一套完整的工程下来,然后全编一下,一般这个时间比较长,大概会得2,3个小时左右, 2,编译成 ...
- 【流媒体开发】VLC Media Player - Android 平台源码编译 与 二次开发详解 (提供详细800M下载好的编译源码及eclipse可调试播放器源码下载)
作者 : 韩曙亮 博客地址 : http://blog.csdn.net/shulianghan/article/details/42707293 转载请注明出处 : http://blog.csd ...
- Android系统篇之—-编写简单的驱动程序并且将其编译到内核源码中【转】
本文转载自:大神 通过之前的一篇文章,我们了解了 Android中的Binder机制和远程服务调用 在这篇文章中主要介绍了Android中的应用在调用一些系统服务的时候的原理,那么接下来就继续来介绍一 ...
- Golang源码探索(二) 协程的实现原理(转)
Golang最大的特色可以说是协程(goroutine)了, 协程让本来很复杂的异步编程变得简单, 让程序员不再需要面对回调地狱,虽然现在引入了协程的语言越来越多, 但go中的协程仍然是实现的是最彻底 ...
- Golang源码探索(三) GC的实现原理(转)
Golang从1.5开始引入了三色GC, 经过多次改进, 当前的1.9版本的GC停顿时间已经可以做到极短.停顿时间的减少意味着"最大响应时间"的缩短, 这也让go更适合编写网络服务 ...
- Android反编译调试源码
Android反编译调试源码 1. 反编译得到源码 直接在windows 命令行下输入命令java -jar apktool_2.0.0.jar d -d 小米运动_1.4.641_1058.apk ...
- Mac 10.14.4 编译openjdk1.9源码 及集成clion动态调试
警告⚠️:本文耗时很长,先做好心理准备:编译openjdk源码需要很大的耐心,因为要踩很多坑,解决很多问题,本人从编译开始到结束用了两天时间,按照本篇教程踩坑会少许:谢谢观看 一.获取openjdk源 ...
- 如何编译和调试Python内核源码?
目录 写在前面 获取源代码 源代码的组织 windows下编译CPython 调试CPython 小结 参考 博客:blog.shinelee.me | 博客园 | CSDN 写在前面 如果对Pyth ...
随机推荐
- Centos7使用yum快速安装ansible
ansible功能简介:ansible可以实现批量系统配置.批量软件部署.批量文件拷贝.批量运行命令等功能.主要基于ssh实现连接各个被控制端 yum默认安装的ansible,常用的配置文件有两个,一 ...
- 在VS2013、VS2015下如何配置DirectX SDK的开发环境
在Visual Studio 2013下配置DirectX SDK可以进行基于DirectX的3D大型应用程序的开发.如果在开发DirectX程序时不配置其开发环境会引起编译器报错, 下面就与大家分享 ...
- Centos6.9部署Gitlab-11.9.8并汉化
Git 是一种分布式的代码版本管理系统,git在工作时可以不用时刻依赖后台服务器,在本地电脑上就可以管理版本控制,但是在需要协同开发时就必须要使用后台服务器了,目前互联网上有github,码云这样的远 ...
- Git 环境配置
Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量. 这些变量存储在三个不同的位置: /etc/gitconfig 文件: 包含系统上每一个用户及他们仓库的通用 ...
- 如何清除Windows10中的恢复分区
在Windows搜索框中键入Cmd.出现结果列表. 右键单击命令提示符并选择以管理员身份运行. 在命令提示符下键入diskpart,然后按Enter键. 输入list disk并按Enter键. 出现 ...
- h5动画如何实现?如何快速开发h5动画
最近几年随着h5的兴起,复杂的h5动画,甚至是交互动画类型的产品不断涌现,尤其在课件产品方面,很多公司都有相关需求,最近很多h5开发工程师想了解相关方面的技术. 针对h5,如果是简单的动画效果,可以考 ...
- C语言volatile关键字的用法
volatile关键字的意义在于让被关键字修饰的变量每次使用时都重新去主内存里读取变量,而不是从高速缓存去读取. int a = 1; 普通变量定义之后,若要使用它,都会 先把它的值从主内存拷贝到高速 ...
- Tomcat 多个虚拟主机配置方法
conf/server.xml 移除注释内容后,类似内容如下: <Server> …… …… …… <Service name="Catalina"> &l ...
- 解决用低版本的客户端ORACLE 12提示ORA-28040的异常
用低版本的客户端访问ORACLE 12,无法连接,提示信息为ORA-28040.解决办法如下: 1.把sqlnet.ora文件添加两行(或者修改),修改文件后直接生效,不需要重启服务和监听的: SQL ...
- 黄聪:mysql主从配置(清晰的思路)
mysql主从配置.鄙人是在如下环境测试的: 主数据库所在的操作系统:win7 主数据库的版本:5.0 主数据库的ip地址:192.168.1.111 从数据库所在的操作系统:linux 从数据的版本 ...