Go工具和调试详解

栏目: C · 发布时间: 7年前

内容简介:-gcflags: 传递给编译器的参数-ldflags: 传递给链接器的参数-work: 查看编译临时目录

工具集

go build

-gcflags: 传递给编译器的参数

-ldflags: 传递给链接器的参数

-work: 查看编译临时目录

-race: 允许数据竞争检测(仅支持amd64)

-n: 查看但不执行编译指令

-x: 查看并执行编译命令

-a: 强制重新编译所有依赖包

-v: 查看被编译的包名,包括依赖包

-p n:并行编译所使用的CPU数,默认为全部

-o:输出文件名

gcflags:

-B 禁用边界检查

-N 禁用优化

-l 禁用函数内联

-u 禁用unsafe代码

-m 输出优化信息

-S 输出汇编代码

ldflags:

-w 禁用DRAWF调试信息,但不包括符号表

-s 禁用符号表

-X 修改字符串符号值  -X main.VER ‘0.99’  -X main.S ‘abc’

-H 链接文件类型,其中包括windowsgui.   cmd/ld/doc.go

更多参数:

go tool compile -h

go tool link  -h

go install

和go build参数相同,将生成文件拷贝到bin,pkg目录,优先使用GOBIN环境变量指定目录

go clean

-n 查看但不执行清理命令

-x 查看并执行清理命令

-i 删除bin,pkg目录下的二进制文件

-r 清理所有依赖包临时目录

go get

-d 仅下载,不执行安装命令

-t 下载测试所需依赖包

-u 更新包包括其依赖

-v 查看并执行命令

go tool objdump

反汇编可执行文件

go tool objdump -s “main\.\w+” test

条件编译

(一)  GOOS GOARCH

通过runtime.GOOS/GOARCH判断,或使用编译约束标记

// +build darwin linux

ß-----必须有空行,以区别包文档。

package main

在源文件(.go, .h, .c, .s等)头部添加”+build”注释,指示编译器检查相关环境变量。

多个约束标记会合并处理。其中空格表示OR,逗号AND,感叹号NOT。

// +build darwin linux  -------à合并结果(darwin OR linux)AND (amd64 AND (NOT cgo))

// +build amd64,!cgo

如果GOOS,GOARCH不符号,编译器会忽略该文件

(二)   文件名

还可使用文件名来表示编译约束,比如test_darwin_amd64.go.使用文件名拆分多个不同平台源文件,更利于维护。

-rw-r--r--@1 zhangxiaoan admin 11545 11 29 05:38 os_darwin.c

-rw-r--r--@1 zhangxiaoan admin 1382 11 29 05:38 os_darwin.h

-rw-r--r--@1 zhangxiaoan admin 6990 11 29 05:38 os_freebsd.c

-rw-r--r--@1 zhangxiaoan admin 791 11 29 05:38 os_freebsd.h

-rw-r--r--@1 zhangxiaoan admin 644 11 29 05:38 os_freebsd_arm.c

-rw-r--r--@1 zhangxiaoan admin 8624 11 29 05:38 os_linux.c

-rw-r--r--@1 zhangxiaoan admin 1067 11 29 05:38 os_linux.h

-rw-r--r--@1 zhangxiaoan admin 861 11 29 05:38 os_linux_386.c

-rw-r--r--@ 1zhangxiaoan admin 2418 11 29 05:38 os_linux_arm.c

⽀支持:*_GOOS、*_GOARCH、*_GOOS_GOARCH、*_GOARCH_GOOS 格式。

可忽略某个文件,或指定编译器版本号。更多信息参考标准库go/build文档。

// +build ignore

// +build go1.2 ß------最低需要 go 1.2编译

(三)  自定义约束条件

需使用”go build -tags”参数。

跨平台编译

首先得生成与平台相关的 工具 和标准库

$ cd/usr/local/go/src

$GOOS=linux GOARCH=amd64 ./make.bash --no-clean

#Building C bootstrap tool.

cmd/dist

#Building compilers and Go bootstrap tool for host, darwin/amd64.

cmd/6l

cmd/6a

cmd/6c

cmd/6g

...

---

InstalledGo for linux/amd64 in /usr/local/go

Installed commands in/usr/local/go/bin

--no-clean参数避免清除其他平台文件

然后回到项目所在目录,设定GOOS,GOARCH环境变量即可编译目标平台文件

$GOOS=linux GOARCH=amd64 go build -o test

$ filetest

learn:ELF 64-bit LSB executable, x86-64, version 1 (SYSV)

$ uname-a

Darwin Kernel Version12.5.0: RELEASE_X86_64 x86_64

GO GDB语言调试

gdb不能很好的理解GO程序.即使使用gccgo,栈管理,线程和运行时与GDB期望的执行模式也不完全一样。因此GDB对GO程序并不完全可靠,尤其是在调试并发程序时。

GO程序包含DWARF3调试信息,GDB7.1以上版本可以进行调试。.

传递”-w”选项给链接器会去除调试信息。(比如:go build -ldflags “-w” prog.go)

gc编译器生成的代码包含内联函数和寄存器变量优化,可以通过-gcflags “-N -l”去掉优化

常用操作

·         显示代码文件和行号信息,设置断点和查看反汇编 :

·         (gdb) list

·         (gdb) list line

·         (gdb) list file.go : line

·         (gdb) break line

·         (gdb) break file.go : line

(gdb) disas

·         显示 backtraces stack frames:

·         (gdb) bt

(gdb) frame n

·         显示名称,类型和栈上的本地变量,参数和返回值 :

·         (gdb) info locals

·         (gdb) info args

·         (gdb) p variable

(gdb) whatis variable

·         显示名称,类型和全局变量的位置 :

(gdb) info variables regexp

go扩展

GDB最新的扩展机制允许为二进制程序加载扩展脚本。工具链使用这个机制为GDB扩展一些命令来监控运行代码的内部(如goroutines)和内置map,slice,和通道的清晰打印.

如果GDB不能找到扩展脚本,可以手工执行:

(gdb) source/usr/lib/golang/src/runtime/runtime-gdb.py

·         打印 string, slice, map, channel orinterface:

(gdb) p var

·         strings, slices maps $len() $cap() 函数 :

(gdb) p $len( var )

·         转换接口为它们的动态类型 :

·         (gdb) p $dtype( var )

(gdb) iface var

·         查看协程 :

·         (gdb) info goroutines

·         (gdb) goroutine n cmd

(gdb) help goroutine

举例 :

(gdb) goroutine 12 bt

已知问题

字符串的清晰打印只对原始字符串类型有效,从其派生的类型无效

运行库的C代码部分没有类型信息

GDB不理解GO的命名方式, 包中的类型的函数形式为 pkg.(*MyType).Meth

所有的全局变量集中到包”main”

教程

通过regexp包的单元测试程序来演示GDB的使用。

构建程序:cd $GOROOT/src/regexp; go test -c

生成可执行程序regexp.test

$ gdb regexp.test

GNU gdb (GDB) 7.2-gg8

Copyright (C) 2010 Free Software Foundation, Inc.

License GPLv  3+: GNU GPL version 3or later <http://gnu.org/licenses/gpl.html>

Type "show copying" and "show warranty" forlicensing/warranty details.

This GDB was configured as "x86_64-linux".

Reading symbols from /home/user/go/src/regexp/regexp.test...

done.

Loading Go Runtime support.

(gdb)

"Loading Go Runtime support"   意味着 GDB 加载了扩展   $GOROOT/src/runtime/runtime-gdb.py .

如果没有自动加载,可以手工加载 :

(gdb) source/usr/lib/go/src/runtime/runtime-gdb.py

Loading Go Runtime support.

查看代码

使用   "l"     "list" 命令查看源代码 .

(gdb) l

通过函数名显示源代码的特定部分 ( 必须包含其包名 ).

(gdb) l main.main

显示特定文件和行号

(gdb) l regexp.go:1

(gdb) # Hit enter to repeat last command. Here, this lists next 10lines.

关于命名

变量和函数名必须携带其所属的包名。regexp包中的Compile函数被GDB当作’regexp.Compile’

方法必须包含其接收着类型。比如,*Regexp类型的String方法必须写在’regexp.(*Regexp).String’

引用其它变量的类型在调试信息中被加上了一个数字后缀,被闭包引用的变量将会显示为一个添加&前缀的指针

设置断点

TestFind 函数设置断点 :

(gdb) b 'regexp.TestFind'

Breakpoint 1 at 0x424908: file /home/user/go/src/regexp/find_test.go, line148.

运行程序 :

(gdb) run

Starting program: /home/user/go/src/regexp/regexp.test

Breakpoint 1, regexp.TestFind (t=0xf8404a89c0) at/home/user/go/src/regexp/find_test.go:148

148  func TestFind(t *testing.T) {

执行在断点处暂停。查看哪个协程正在运行 :

(gdb) info goroutines

1 waiting runtime.gosched

* 13  running runtime.goexit

标记着   *   的为当前正在运行的协程

查看栈.

在程序暂停的地方查看栈回溯 :

(gdb) bt # backtrace

#0  regexp.TestFind (t=0xf8404a89c0)at /home/user/go/src/regexp/find_test.go:148

#1  0x000000000042f60b intesting.tRunner (t=0xf8404a89c0, test=0x573720) at/home/user/go/src/testing/testing.go:156

#2  0x000000000040df64 inruntime.initdone () at /home/user/go/src/runtime/proc.c:242

#3  0x000000f8404a89c0 in ?? ()

#4  0x0000000000573720 in ?? ()

#5  0x0000000000000000 in ?? ()

另外一个协程1,阻塞在通道接收 :

(gdb) goroutine 1 bt

#0  0x000000000040facb inruntime.gosched () at /home/user/go/src/runtime/proc.c:873

#1  0x00000000004031c9 inruntime.chanrecv (c=void, ep=void, selected=void, received=void)

at /home/user/go/src/runtime/chan.c:342

#2  0x0000000000403299 inruntime.chanrecv1 (t=void, c=void) at/home/user/go/src/runtime/chan.c:423

#3  0x000000000043075b intesting.RunTests (matchString={void (struct string, struct string, bool *,error *)}

0x7ffff7f9ef60, tests=  []testing.InternalTest = {...}) at/home/user/go/src/testing/testing.go:201

#4  0x00000000004302b1 in testing.Main(matchString={void (struct string, struct string, bool *, error *)}

0x7ffff7f9ef80, tests=[]testing.InternalTest = {...}, benchmarks= []testing.InternalBenchmark ={...})

at /home/user/go/src/testing/testing.go:168

#5  0x0000000000400dc1 in main.main() at /home/user/go/src/regexp/_testmain.go:98

#6  0x00000000004022e7 inruntime.mainstart () at /home/user/go/src/runtime/amd64/asm.s:78

#7  0x000000000040ea6f inruntime.initdone () at /home/user/go/src/runtime/proc.c:243

#8  0x0000000000000000 in ?? ()

栈桢显示我们当前在执行   regexp.TestFind   函数 .

(gdb) info frame

Stack level 0, frame at 0x7ffff7f9ff88:

rip = 0x425530 in regexp.TestFind(/home/user/go/src/regexp/find_test.go:148);

saved rip 0x430233

called by frame at 0x7ffff7f9ffa8

source language minimal.

Arglist at 0x7ffff7f9ff78, args:t=0xf840688b60

Locals at 0x7ffff7f9ff78, Previousframe's sp is 0x7ffff7f9ff88

Saved registers:

rip at 0x7ffff7f9ff80

命令 info locals 显示函数的所有本地变量,   但是这个命令有一定风险,因为它会尝试打印未初始化的变量。可能造成 gdb 打印很大的数组 .

查看函数参数 :

(gdb) info args

t = 0xf840688b60

打印参数时显示的时一个指向   Regexp 值的指针 .

注意 GDB 错误地将 * 放在了类型名的右边 .

(gdb) p re

(gdb) p t

$1 = (struct testing.T *) 0xf840688b60

(gdb) p t

$1 = (struct testing.T *) 0xf840688b60

(gdb) p *t

$2 = {errors = "", failed = false, ch = 0xf8406f5690}

(gdb) p *t->ch

$3 = struct hchan<*testing.T>

struct hchan<*testing.T> 是通道运行时的内部表示 . 它当前为空 , 否则 gdb 会清晰地打印其内容 .

继续执行 :

(gdb) n # execute nextline

149             for _, test := rangefindTests {

(gdb)    # enter is repeat

150                     re :=MustCompile(test.pat)

(gdb) p test.pat

$4 = ""

(gdb) p re

$5 = (struct regexp.Regexp *) 0xf84068d070

(gdb) p *re

$6 = {expr = "", prog = 0xf840688b80, prefix = "",prefixBytes =  []uint8, prefixComplete =true,

prefixRune = 0, cond = 0 '\000',numSubexp = 0, longest = false, mu = {state = 0, sema = 0},

machine =  []*regexp.machine}

(gdb) p *re->prog

$7 = {Inst =  []regexp/syntax.Inst ={{Op = 5 '\005', Out = 0, Arg = 0, Rune = []int}, {Op =

6 '\006', Out = 2, Arg = 0, Rune=  []int}, {Op = 4 '\004', Out = 0, Arg =0, Rune =  []int}},

Start = 1, NumCap = 2}

我们能够跟进 String 函数通过调用 ”s”:

(gdb) s

regexp.(*Regexp).String (re=0xf84068d070, noname=void) at/home/user/go/src/regexp/regexp.go:97

97      func (re *Regexp) String()string {

通过 bt 查看我们执行到哪里 :

(gdb) bt

#0  regexp.(*Regexp).String(re=0xf84068d070, noname=void)

at/home/user/go/src/regexp/regexp.go:97

#1  0x0000000000425615 inregexp.TestFind (t=0xf840688b60)

at/home/user/go/src/regexp/find_test.go:151

#2  0x0000000000430233 intesting.tRunner (t=0xf840688b60, test=0x5747b8)

at/home/user/go/src/testing/testing.go:156

#3  0x000000000040ea6f inruntime.initdone () at /home/user/go/src/runtime/proc.c:243

....

查看源代码 :

(gdb) l

92              mu      sync.Mutex

93              machine []*machine

94      }

95

96      // String returns the sourcetext used to compile the regular expression.

97      func (re *Regexp) String()string {

98              return re.expr

99      }

100

101     // Compile parses a regularexpression and returns, if successful,

清晰打印

GDB's pretty printing mechanism is triggered by regexpmatches on type names. An example for slices:

(gdb) p utf

$22 =  []uint8 = {0 '\000', 0'\000', 0 '\000', 0 '\000'}

因为 slices, arrays strings 不是 C 指针 ,GDB 不能解释带下标的操作,但是你可以通过下面的方式查看其内容 ( 使用 tab 帮助完成 ):

(gdb) p slc

$11 =  []int = {0, 0}

(gdb) p slc-> <TAB>

array  slc    len   

(gdb) p slc->array

$12 = (int *) 0xf84057af00

(gdb) p slc->array[1]

$13 = 0

扩展函数 $len $cap 支持 strings, arrays slices:

(gdb) p $len(utf)

$23 = 4

(gdb) p $cap(utf)

$24 = 4

通道和 maps 是引用类型, gdb 显示为类似 C++ 的指针类型   hash<int,string>* . 解引用操作将会触发清晰打印

接口在运行时表示为一个指向类型描述的指针和一个指向值的指针 .

Go GDB 运行扩展对运行时类型解码并自动触发清晰打印 .

扩展函数 $dtype   为你解码运行时类型 ( 例子在   regexp.go   293 .)

(gdb) p i

$4 = {str = "cbb"}

(gdb) whatis i

type = regexp.input

(gdb) p $dtype(i)

$26 = (struct regexp.inputBytes *) 0xf8400b4930

(gdb) iface i

regexp.input: struct regexp.inputBytes *


以上所述就是小编给大家介绍的《Go工具和调试详解》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Design and Analysis of Distributed Algorithms (Wiley Series on P

Design and Analysis of Distributed Algorithms (Wiley Series on P

Nicola Santoro / Wiley-Interscience / 2006-10-27 / USD 140.95

This text is based on a simple and fully reactive computational model that allows for intuitive comprehension and logical designs. The principles and techniques presented can be applied to any distrib......一起来看看 《Design and Analysis of Distributed Algorithms (Wiley Series on P》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换