文档章节

debugger

精通吹水
 精通吹水
发布于 2016/04/17 10:37
字数 1515
阅读 74
收藏 3
点赞 1
评论 0

debugger

文本将介绍调试器如何实现断点,单步,即时执行函数的功能。

GDB

在Linux C编程中,一般都使用GDB来进行调试代码。通过GDB我们可以实现断点,单步,即时执行这些调试手段。

INT 3 和 断点

80x86 CPU调试的核心就是通过INT 3 (80x86 CPU)中断来实现。当执行INT 3 的时候,在Linux中会引发SIGTRAP信号。从而进一步的实现具体的功能:查看变量,即时执行...。

而断点的实现就是通过INT 3来实现,实现的流程如下:

  1. 寻找到代码中被下断点的内存位置
  2. 记录原先位置的指令
  3. 使用INT 3来替换该指令,如果长度不符合,则使用NOP来填充。

这么做是因为涉及到偏移量的问题,不能简单的插入INT 3指令,而是采用替换的方式。这样子,就完成了打断点的功能。而当代码执行到刚刚下断点(INT 3指令)的时候,会执行如下流程:

  1. INT 3指令引发中断门
  2. Linux内核切换当前任务(被调试程序)到阻塞状态
  3. Linux唤醒调试器(GDB)告知被调试程序现在处于中断状态

此时,我们就可以通过GDB来查看被调试程序的变量,堆栈等信息。

TSS

那么问题来了:刚刚被INT 3替换的指令,如何执行?因为被调试程序的用户态EIP已经指向了INT 3下一条指令了

首先我们需要了解一下Linux下TSS的概念:

任务状态段(Task State Segment)是保存一个任务重要信息的特殊段。 TSS在任务切换过程中起着重要作用,通过它实现任务的挂起和恢复。所谓任务切换是指,挂起当前正在执行的任务,恢复或启动另一任务的执行。在任务切换过程中,首先,处理器中各寄存器的当前值被自动保存到TR所指定的TSS中;然后,下一任务的TSS的选择子被装入TR;最后,从TR所指定的TSS中取出各寄存器的值送到处理器的各寄存器中。由此可见,通过在TSS中保存任务现场各寄存器状态的完整映象,实现任务的切换。

所以在Linux中,是通过TSS来描述一个程序运行的状态,并且进行多任务轮转的。TSS结构图:

TSS

还原被替换的指令,然后通过修改EIP寄存器,将它指向被替换指令地址,因此被调试的程序可以执行刚刚被替换的指令。

JMP/CALL

80x86 CPU的EIP寄存器不能直接修改,而是需要通过专门指令来修改EIP寄存器:

  1. JMP : 直接跳转到指定目标代码
  2. CALL: 进行调用制定代码目标函数

在多任务模式下,通过JMP/CALL + TSS 来完成任务的切换。如:

jmp 0x1000:0x10000000 #TSS地址

这样子,就实现了任务的切换。

即时运行

即时运行指的是使用** GDB CALL 命令**来完成运行函数的功能。

这个功能和下断点的原理基本一致,也是通过替换指令和插入INT 3来完成。完成运行后,再还原之前被替换的代码,并且修改TSS中的EIP寄存器数值。

所以,即时运行的调用栈就是使用原先的调用栈,而非新开一个THREAD来执行即时运行代码。

JVM

Java的调试技术是非常成熟的,我们可以通过各种方式来调试Java代码,这也是VM的强大之处。

即时运行

在调试的时候,我们想知道一段代码执行的结果是什么。比如说,System.out.println(var)。这时候就需要使用即时运行的功能。

而即时运行功能也和GDB实现类似,调用栈也是使用原先的调用栈,而非新开THREAD运行及时代码:

public class Main {
	static public void main(String args[]) {
		Main main = new Main();
		main.a();
	}

	public void a() {
		System.out.println("A");
	}

	public void stack() {
		try {
			throw new RuntimeException("A");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

断点处运行:

Call Stack

执行结果为:

java.lang.RuntimeException: A
	at Main.stack(Main.java:18)
	at Main.a(Main.java:13)
	at Main.main(Main.java:9)

所以,及时运行的调用栈环境就是断点位置的环境。

远程调试

JVM也支持远程调试,这个功能对排查线上BUG是非常方便的,而这个功能是通过SOCKET来完成。

JVM调试参数:

-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,address=3999,suspend=n

说明:

参数含义
-XDebug启用调试。
-Xnoagent禁用默认sun.tools.debug调试器。
-Djava.compiler=NONE禁止 JIT 编译器的加载。
-Xrunjdwp加载JDWP的JPDA参考执行实例。
transport用于在调试程序和 VM 使用的进程之间通讯。
dt_socket套接字传输。
dt_shmem共享内存传输,仅限于 Windows。
server=y/nVM 是否需要作为调试服务器执行。
address=3999调试服务器的端口号,客户端用来连接服务器的端口号。
suspend=y/n是否在调试客户端建立连接之后启动 VM 。

这样子,就开启了JVM的调试功能,然后通过远程调试器连接上,既可以进行调试了。

因为通过Socket调试非常的方便,所以现在流行的语言基本上都支持远程调试的功能。

日志

在某些时候(生产环境),我们不能通过调试器来完成调试的功能,此时我们需要借助最原始的方式:日志

总结

一个好用的DEBUGGER能极大的增加软件开发效率。

参考

© 著作权归作者所有

共有 人打赏支持
精通吹水
粉丝 18
博文 56
码字总数 55035
作品 0
人事招聘
求zend+xdebug环境 php达人赐教断点调试表单的用法!!!

wind环境下的zend debugger+firefox的插件(zend debugger tools) 一直是用的很好.可是坑爹的是 由于要跟上php的步伐.开始要用5.3了. 可以zend debugger 非要出nts版的. windows据说只有zend ...

callmez ⋅ 2012/09/11 ⋅ 0

Java 远程调试

写服务端程序,在开发环境下打开远程调试还是非常有用的,还原现场非常容易,让请求方再发个请求即可。如果下来本地调试的话很多环境与管理服务的地址配置什么的都可能不一样,增加了可变因素...

mrliuze ⋅ 2016/07/28 ⋅ 0

您好,我看了您关于配置zend debugger的文章,test debugger为什么 会失败的?

@feek 你好,想跟你请教个问题: test debugger为什么 会失败的 。 以下是我php.ini的配置 zendextensionts="E:/APMServ5.2.6/PHP/ext/ZendDebugger.dll" zenddebugger.allowhosts=127.0.0.1......

pandamf ⋅ 2014/05/07 ⋅ 0

一站式页面调试工具--Spy-Debugger

关于spy-debugger 1、一站式页面调试工具,远程调试任何手机浏览器页面,任何手机移动端webview(如:微信,HybirdApp等)HTTP/HTTPS。 2、spy-debugger内部集成了weinre。 3、支持HTTPS页面...

wuchangming ⋅ 2016/04/26 ⋅ 1

安装EPP的调试Zend Debugger

最近在工作中遇到的一个问题就是PHP程序的调试,PHP的程序可以直接在页面中显示出错误信息,但是如果是较大较复杂的程序,这种方式的开发效率就极其低下了,那么如何在IDE中可以对程序进行单...

王二狗子11 ⋅ 01/08 ⋅ 0

Eclipse支持PHP

Eclipse支持PHP使用Zend Debugger调试 一、安装Eclipse 下载地址为http://www.eclipse.org/downloads/ 上面有好多个版本,通过Compare Packages科研看到其中的区别。开发PHP的话,Eclipse I...

durban ⋅ 2012/08/16 ⋅ 0

调试你的Python代码

## 调试你的Python代码 http://howchoo.com/g/zgi2y2iwyze/debugging-your-python-code 作者 Ashley 当你不得不更新别人的代码时,你有多少次陷入这样一种境地?如果你是一个开发团队的一员,...

Marmot_Alex ⋅ 2015/03/23 ⋅ 0

DEX(classes.dex 文件)代码动态调试检测

sec-andr-002 DEX(classes.dex 文件)代码动态调试检测 Android渗透测试示例 测试描述: 在 DEX 文件未加密的基础上,利用第三方工具对客户端代码进行动态调试,对 JAVA 层数据进行获取和篡改...

Ho0oH ⋅ 2017/09/26 ⋅ 0

ABAP如何在调试查看EXPORT/IMPORT 内存数据

These memory IDs can be accessed in the debugger, but the option isn't accessible by default in the "new" Debugger. To display them you have two options: In the new Debugger, ch......

zhongguomao ⋅ 03/09 ⋅ 0

Java HotSpot VM 命令行参数【官方版】

Java HotSpot VM Command-Line Options Command-line options that are prefixed with are specific to the Java HotSpot Virtual Machine. Many of these options are important for perfor......

nj-zhangmq ⋅ 2016/12/22 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

vuex学习

1、getters基本用法: 在store.js里面用const声明我们的getters属性。 const getters={ count:function (state) { return state.count +=100; }} export default new Vuex.S......

大美琴 ⋅ 43分钟前 ⋅ 0

292. Nim Game - LeetCode

Question 292. Nim Game Solution 思路:试着列举一下,就能发现一个n只要不是4的倍数,就能赢。 n 是否能赢1 true2 true3 true4 false 不论删除几,对方都能一把赢5 t...

yysue ⋅ 54分钟前 ⋅ 0

G6 关系数据可视化图形库 简单使用

官网 https://antv.alipay.com/zh-cn/g6/1.x/index.html 效果 首先生成给定数目的小球,并设置随机的颜色 按照顺序,设置小球的角度以及坐标 设置定时器,每隔一定的时间修改小球的角度和坐标...

阿豪boy ⋅ 57分钟前 ⋅ 0

6.5 zip压缩工具 6.6 tar打包 6.7 打包并压缩

zip压缩工具 zip命令可以压缩目录和文件,-r 压缩目录。 zip使用方法 zip 1.txt.zip 1.txt //压缩文件 zip -r 123.zip 123/ //压缩目录 unzip 1.txt.zip //解压 unzip 123.zip -d /root/456...

Linux_老吴 ⋅ 今天 ⋅ 0

react-loadable使用跳坑

官方给react-loadable的定义是: A higher order component for loading components with dynamic imports. 动态路由示例 withLoadable.js import React from 'react'import Loadable fro......

pengqinmm ⋅ 今天 ⋅ 0

记录工作中遇到的坑

1、ios safari浏览器向下滚动会触发window resize事件

端木遗风 ⋅ 今天 ⋅ 0

桥接设计模式

1、概述: 将抽象部分与他的实现部分分离,这样抽象化与实现化解耦,使他们可以独立的变化 如何实现解耦的呢,就是通过提供抽象化和实现化之间的桥接结构 桥接模式将继承模式转化成关联关系,他降...

职业搬砖20年 ⋅ 今天 ⋅ 0

20.zip压缩 tar打包 打包并压缩

6月25日任务 6.5 zip压缩工具 6.6 tar打包 6.7 打包并压缩 6.5 zip压缩工具: zip支持压缩目录 zip压缩完之后原来的文件不删除 不同的文件内容其实压缩的效果不一样 文件内有很多重复的用xz压...

王鑫linux ⋅ 今天 ⋅ 0

double类型数据保留四位小数的另一种思路

来源:透析公式处理,有时候数据有很长的小数位,有的时候由在四位以内,如果用一般的处理方法,那么不足四位的小树会补充0到第四位,这样子有点画蛇添足的感觉,不太好看。所以要根据小数的...

young_chen ⋅ 今天 ⋅ 0

Django配置163邮箱出现 authentication failed(535)错误解决方法

最近用Django写某网站,当配置163邮箱设置完成后,出现535错误即:smtplib.SMTPAuthenticationError: (535, b'Error: authentication failed') Django初始配置邮箱设置 EMAIL_HOST = "smtp.1...

陈墨轩_CJX ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部