go语言汇编调试 go语言反汇编

调试Go语言的核心转储(Core Dumps)英文原文链接【Go, the unwritten parts】发表于2017/05/22 作者JBD是Go语言开发小组成员
检查程序的执行路径和当前状态是非常有用的调试手段 。核心文件(core file)包含了一个运行进程的内存转储和状态 。它主要是用来作为事后调试程序用的 。它也可以被用来查看一个运行中的程序的状态 。这两个使用场景使调试文件转储成为一个非常好的诊断手段 。我们可以用这个方法来做事后诊断和分析线上的服务(production services) 。
在这篇文章中,我们将用一个简单的hello world网站服务作为例子 。在现实中,我们的程序很容易就会变得很复杂 。分析核心转储给我们提供了一个机会去重构程序的状态并且查看只有在某些条件/环境下才能重现的案例 。
作者注 : 这个调试流程只在Linux上可行 。我不是很确定它是否在其它Unixs系统上工作 。macOS对此还不支持 。Windows现在也不支持 。
在我们开始前,需要确保核心转储的ulimit设置在合适的范围 。它的缺省值是0 , 意味着最大的核心文件大小是0 。我通常在我的开发机器上将它设置成unlimited 。使用以下命令:
接下来 , 你需要在你的机器上安装 delve。
下面我们使用的 main.go 文件 。它注册了一个简单的请求处理函数(handler)然后启动了HTTP服务 。
让我们编译并生产二进制文件 。
现在让我们假设 , 这个服务器出了些问题,但是我们并不是很确定问题的根源 。你可能已经在程序里加了很多辅助信息,但还是无法从这些调试信息中找出线索 。通常在这种情况下,当前进程的快照会非常有用 。我们可以用这个快照深入查看程序的当前状态 。
有几个方式来获取核心文件 。你可能已经熟悉了奔溃转储(crash dumps) 。它们是在一个程序奔溃的时候写入磁盘的核心转储 。Go语言在缺省设置下不会生产奔溃转储 。但是当你把 GOTRACEBACK 环境变量设置成“crash” , 你就可以用 Ctrl backslash 才触发奔溃转储 。如下图所示:
上面的操作会使程序终止,将堆栈跟踪(stack trace)打印出来,并把核心转储文件写入磁盘 。
另外个方法可以从一个运行的程序获得核心转储而不需要终止相应的进程 。gcore 可以生产核心文件而无需使运行中的程序退出 。
根据上面的操作 , 我们获得了转储而没有终止对应的进程 。下一步就是把核心文件加载进delve并开始分析 。
差不多就这些 。delve的常用操作都可以使用 。你可以backtrace , list , 查看变量等等 。有些功能不可用因为我们使用的核心转储是一个快照而不是正在运行的进程 。但是程序执行路径和状态全部可以访问 。
【接口测试】Go语言进行简单的接口测试在正常的测试中go语言汇编调试,当go语言汇编调试我们需要进行接口测试时 , 通常使用接口调试工具 , 如postman进行接口测试
目前我在尝试使用Go语言进行接口测试,使用的库均为Go自带的库 。
注go语言汇编调试:当前采用的接口为时事新闻接口,每天可以请求100次 , 需要的同学,可以自行使用 。
Go语言编译成aar并调试 go及gomobilego语言汇编调试的环境配置这里就不介绍了go语言汇编调试 , 直接说aargo语言汇编调试的生成和使用 。
1. 设置环境变量GOPATH
GOPATH的值可以有多个go语言汇编调试,用半角分号间隔go语言汇编调试,但不能以其结束,设置完成后需要重新做 gomobile init。
2. 在GOPATH里创建src文件夹,用于存放go的包和源文件
3. 在src中创建hello文件夹(go文件的包名)
4. 在hello中创建hello.go文件,并输入内容
5. 编译
执行命令: gomobile bind -target=android hello
会生成一个hello.aar文件
6. 导入到android工程
将hello.aar文件放入工程的libs中 , 并配置build.gradle
在根结点加入:
在dependencies结点下加入依赖:
7. 在Java中测试
运行后,结果会输出 Hello, Android and Gopher
GO语言学习系列八——GO函数(func)的声明与使用 GO是编译性语言go语言汇编调试,所以函数的顺序是无关紧要的go语言汇编调试,为了方便阅读,建议入口函数 main 写在最前面 , 其余函数按照功能需要进行排列
GO的函数 不支持嵌套,重载和默认参数
GO的函数 支持 无需声明变量 , 可变长度 , 多返回值,匿名,闭包等
GO的函数用 func 来声明 , 且左大括号 { 不能另起一行
一个简单的示例:
输出为:
参数:可以传0个或多个值来供自己用
返回:通过用 return来进行返回
输出为:
上面就是一个典型的多参数传递与多返回值
对例子的说明:
按值传递:是对某个变量进行复制,不能更改原变量的值
引用传递:相当于按指针传递,可以同时改变原来的值 , 并且消耗的内存会更少,只有4或8个字节的消耗
在上例中 , 返回值 (d int, e int, f int) { 是进行了命名,如果不想命名可以写成 (int,int,int){ ,返回的结果都是一样的,但要注意:
当返回了多个值,我们某些变量不想要,或实际用不到,我们可以使用 _ 来补位,例如上例的返回我们可以写成 d,_,f := test(a,b,c),我们不想要中间的返回值 , 可以以这种形式来舍弃掉
在参数后面以 变量 ... type 这种形式的 , 我们就要以判断出这是一个可变长度的参数
输出为:
在上例中, strs ...string 中,strs 的实际值是b,c,d,e,这就是一个最简单的传递可变长度的参数的例子,更多一些演变的形式 , 都非常类似
在GO中 defer 关键字非常重要,相当于面相对像中的析构函数,也就是在某个函数执行完成后,GO会自动这个;
如果在多层循环中函数里,都定义了 defer ,那么它的执行顺序是先进后出;
当某个函数出现严重错误时, defer 也会被调用
输出为
这是一个最简单的测试了 , 当然还有更复杂的调用,比如调试程序时,判断是哪个函数出了问题,完全可以根据 defer 打印出来的内容来进行判断 , 非常快速 , 这种留给go语言汇编调试你们去实现
一个函数在函数体内自己调用自己我们称之为递归函数,在做递归调用时 , 经常会将内存给占满,这是非常要注意的,常用的比如,快速排序就是用的递归调用
本篇重点介绍了GO函数(func)的声明与使用 , 下一篇将介绍GO的结构 struct
汇编小问题在DOS下的DEBUG命令的详细用法:
名称 解释 格式
a (Assemble) 逐行汇编 a [address]
c (Compare) 比较两内存块 c range address
d (Dump) 内存16进制显示 d [address]或 d [range]
e (Enter) 修改内存字节 e address [list]
f (fin) 预置一段内存 f range list
g (Go) 执行程序 g [=address][address...]
h (Hexavithmetic) 制算术运算 h value value
i (Input) 从指定端口地址输入 i pataddress
l (Load) 读盘 l [address [driver seetor
m (Move) 内存块传送 m range address
n (Name) 置文件名n filespec [filespec...]
o (Output) 从指定端口地址输出 o portadress byte
q (Quit) 结束q
r (Register) 显示和修改寄存器 r [register name]
s (Search) 查找字节串s range list
t (Trace) 跟踪执行t [=address] [value]
u (Unassemble) 反汇编 u [address ]或range
w (Write) 存盘w [address[driver sector secnum
? 联机帮助 ?
debug小汇编a命令
debug小汇编a命令是一个很有用的功能go语言汇编调试,许多的小程序都要go语言汇编调试他来做 。
编一些小程序比汇编要来得方便,快洁 。
在Debug中,中断是非常有用的,首先,让go语言汇编调试我们先了解一下中断 。
所谓中断,其实 , 就是,当你做某事时,有人过来找你有其他事,你先放下手中的事(计算机中,称为保护现?。?
,再去与叫你的那个人办事去,等完了,你又回,接着做刚才的事 。这是个很通俗的讲法 。
计算机在运行时,也会出现这种情况,我们叫之中断 。
下面是他的一些常用中断向量的入口值详解:(记住哦,很用的...呵呵)
IBM PC 中断 int10
ooH 屏幕方式设置
入口:AH=0,AL=显示方式代码(0--6)
0:40*25 黑白
1:40*25 彩色
2:80*25 黑白
3:80*25 彩色文本
4:320*200 彩色
5:320*200 黑白
6:640*200 黑白图形模式
7:80*25 单色字符(单色显示器)
0BH 色彩设置
入口:AH=0B , BL=0 设背景色,BH=0--15BL=1 设调色码,BH=0--1
0CH 写图形点
入口:AH=0C,CX:DX=列号:行号,AL=颜色
ODH 读图形点
入口:AH=0D , CX:DX=列号:行号
返回:AL=颜色
0EH 在当前页、当前光标处写字符
入口:AH=0E,AL=字符的ASCII码 , BL=前景色
OFH 显示器状态
入口:AH=0F
返回:AL=当前显示器方式 , AH=屏幕列数 , BH=当前页号
01H 光标设置
入口:AH=1 , CH=光标起始行号(00--0C),CL=光标结束行号(00--0C)
注:CH > CL
02H 光标定位
入口:AH=2,BH=页号,DH:DL=起始行:列
03H 读光标位置
入口:AH=3,BH=页号 。
返回:DH:DL=起始行:列
06H 窗口上卷
入品:AH=6,AL=窗口上卷行数 , CH:CL-DH:DL 窗口坐标
注:AL=0 卷动整个窗口
07H 窗口下卷
入口:AH=7,AL=窗口下卷行数,CH:CL-DH:DL 窗口坐标
08H 读当前光标处字符和属性
入口:AH=8 , BH=页号 。
返回:AH:AL=字符的颜色:字符的ASCII码
注:颜色代码见下对照表
09H:在当前光标处写字符和属性
注:光标不下移
入口:AH=9,BH=页号 , BL:AL=字符的颜色:字符的ASCII码,CX=重复次数
1 2 3 4 5 6 7 8
BL R G B I R G B
闪烁 字符底色 加亮 字符颜色
中断向量号表
中断号 解释 中断号 解释
0 除数为0错 19 引导装入程序
1 音步中断 1A 日时调用
2 不可屏蔽中断NMI 1B 键盘阻断时得到控制权
3 断电中断(CCH) 1C 时钟中断时得到控制权
4 溢出中断 1D 指向CRT初始参数表
5 屏幕打印中断 1E 指向盒带参数表
6-7 保留 1F 1KB图形模式
8 计时器中断(18.2秒) 20 结束DOS程序
9 键盘中断 21 DOS功能调用
A-D 保留 22 结束地址(建义用EXEC)
E 软盘机中断 23 DOS Crtl-Break退出地址
F 保留 24 DOS致命错向量
10 屏幕I/O调用 25 DOS绝对磁盘读
11 设备检查调用 26 DOS绝对磁盘写
12 存储器检查调用 27 结束程序并驻留(建义用31h)
13 软盘机I/O调用 28-3F DOS保留
14 RS-233I/O调用 40-7F 未用
15 盒带机I/O调用 80-85 BASIC保留
16 键盘I/O调用 86-F0 BASIC解释程序用
17 打印机I/O调用 F1-FF 未用
18 ROM-BASIC入口
指令名详解
call 指令(过程调用)(控制指令-长转移)
详解:
段内直接调用
段内间接调用(寄存器)
段内间接调用(存储器)
段间直接调用
段间间接调用
指令名
jmp 指令(无条件转移指令)(控制指令-长转移)
详解:
段内直接跳转
短段内直接跳转
段内间接跳转(寄存器)
段内间接跳转(存储器)
段间直接跳转
段间间接跳转
指令名
ret 指令(过程返回)(控制指令-长转移)
详解:
段内返回
段内返回立即数加于sp
段间返回
段间返回立即数加于sp
na/jnbe 指令(控制指令-短转移)不小于或不等于时转移
jae/jnb 指令 (控制指令-短转移)大于或等于时转移
jb/jnae 指令 (控制指令-短转移)小于转移
jbe/jna 指令 (控制指令-短转移)小于或等 于转移
jg/jnle 指令(控制指令-短转移)大于转移
jge/jnl 指令 (控制指令-短转移)大于或等于转移
jl/jnge 指令 (控制指令-短转移)小于转移
jle/jng 指令 (控制指令-短转移)小于或等 于转移
je/jz 指令 (控制指令-短转移)等于转移
jne/jnz 指令 (控制指令-短转移)不等于转移
jc 指令 (控制指令-短转移)有进位时转移
jnc 指令 (控制指令-短转移)列进位时转移
jno 指令 (控制指令-短转移)不溢出时转移
jnp/jpo 指令 (控制指令-短转移)奇偶性为奇数时转移
jns 指令 (控制指令-短转移)符号位为"0"转移
jo 指令 (控制指令-短转移)溢出转移
jp/jpe 指令 (控制指令-短转移)奇偶性为偶数时转移
js 指令 (控制指令-短转移)符号位为"1"时转移
loop 指令 (循环控制指令-短转移)cx 不为0时循环
loope/loopz 指令 (循环控制指令-短转移)cx 不为0且标志 z=1 时循环
loopne/loopnz 指令 (循环控制指令-短转移)cx 不为0且标志 z=0 时循环
jcxz 指令 (循环控制指令-短转移)cx 为0时转移

    推荐阅读