`
yesjavame
  • 浏览: 657874 次
  • 性别: Icon_minigender_2
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

asm中导出方法本地变量

阅读更多

在方法出现异常时需要把传入参数值和本地变量值异导出来供分析。之前因为测试的对象都是普通的值,写的loadLocalVarArray能正常工作。

这几天要在方法进入时inject一个long startTime供在方法退出时计算方法方法执行时间,发现如果本地变量是long和double本地变量栈中实际

占用两个位置,而nextLocal和firstLocal是本地变量栈的地址位置,根本无法知道实际的本地变量个数和具体的索引。

当然用for(int i=0;i< nextLocal-firstLocal;i++){

try{ loadLocal(i+firstLocal) }catch(Exception ex){........}

}利用异常来判断是否有某个localIndex是可以牧举出来的,但是这样太猥琐了。

查看GeneratorAdapter发现有一个私有yojgList<Type> localTypes,在visit的时候,本地变量的type会被放在这个数组中。但是存放的方式几乎和栈中差不多。假如有三个double的亦是,栈中是:

firstLocal + 0

firstLocal + 2

firstLocal + 4

这样nextLocal-firstLocal是6,但是loadLocal(6)肯定出异常。而这个list也是把一个type set到对应的位置。这样它就需要把前面没有的地方填null.设置后是这样的:

0 J

1 null

2 J

3 null

4 J

这个list的长度是5,可以正确地 loadLocal(index).但是它是一个私有变量,我只好给GeneratorAdapter增加一个

public int getLocalLength(){
return this.localTypes.size();
}

说明:因为instrumention功能是独立天任何app的,它引用的库在premain中调用,那么如果应用中使用了同样的库而版本不同,则无法再载

入相同的类,因为premain在main之前已经载入了,为了防止版本冲突,我们是把其它 app常用库重新package进来的,这个工作是非常必要的,所以修改源码仍然可以接受。

有了这个getLocalLength()就好办了:

void loadVarArray() {

Type OBJECT_TYPE = Type.getObjectType("java/lang/Object");
int varCnt = getLocalLength();
if (varCnt == 0) { //返回一个空数组
push(0);
newArray(OBJECT_TYPE);
return;
}

/*
* 先检查栈的空位(long和double占两个位,其一个标记为null),如果直接用栈长度指定数组
* 则占位的位置为null,返回出去程序不知道是占位的null还是一个localVar的值为null
*/
int arrLen = 0;
for (int i = 0; i < varCnt; i++) {
Type t = getLocalType(super.firstLocal + i);
if (t != null)
arrLen++;
}
push(arrLen); //实际需要的数组长度
newArray(OBJECT_TYPE);
int arrIndex = 0;
for (int i = 0; i < varCnt; i++) {
int index = super.firstLocal + i;
Type t = getLocalType(index);
if (t == null)
continue;

dup();
push(arrIndex++);
loadLocal(index, t);
box(t);
arrayStore(OBJECT_TYPE);
}
}

这样正确地把所有本地变量加载到数组中(数组现在在操作栈的栈顶,你可以访问它了)。

完整的实现:

分享到:
评论

相关推荐

    构建最高可用Oracle数据库系统 Oracle 11gR2 RAC管理、维护与性能优化

    3.2.3本地注册表 3.3 Clusterware启动流程 3.3.1启动流程 3.3.2后台进程 3.4 Clusterware隔离机制 3.4.1 Clusterware心跳 3.4.2 Clusterware隔离特性IPMI 3.4.3 RAC隔离体系 3.5网格即插即用 3.5.1 GPnP...

    windows用户称拦截api

    如果是想拦截其他进程中的api,则必须使用其他一些方法,最典型的方法是利用VirtualAllocEx函数来在其他进程中申请和提交内存空间。然后用WriteProcessMemory来分别把函数体和参数分别写入申请和分配的内存空间中去...

    NiceBASIC V1.0中文编程正式版(绿色版).rar

    可以使用由标准C语言和汇编ASM编写的静态库(LIB)作为函数功能扩展。可以调用WIN32API的大部分函数,已经在内部定义(.bi文件相当于C语言的.h)声明,直接引用即可,就像C++的WINDOWS开发包(SDK)。 NB的编译器是...

    NiceBASICV 1.0中文编程正式版【MSI安装版】

    可以使用由标准C语言和汇编ASM编写的静态库(LIB)作为函数功能扩展。可以调用WIN32API的大部分函数,已经在内部定义(.bi文件相当于C语言的.h)声明,直接引用即可,就像C++的WINDOWS开发包(SDK)。 NB的编译器是...

    2FFmpeg:使用FFmpeg库进行开发

    回声“导出LD_LIBRARY_PATH = / usr / local / ffmpeg / lib:$ LD_LIBRARY_PATH” &gt;&gt;〜/ .bashrc 回声“导出PKG_CONFIG_PATH = / usr / local / ffmpeg / lib / pkgconfig:$ PKG_CONFIG_PATH” &gt;&gt;〜/ .bashrc 来源...

    Windows环境下32位汇编语言程序设计_随书光盘

    目录中 Test.asm 为例,步骤是: I. 打开一个“命令提示符”窗口。 II. 进入环境设置批处理文件 Var.bat 所在目录并执行 它,以后就可以使用这个“命令提示符”窗口编译 文件了。 x: &lt;切换到MASM32安装的驱动...

    OCPOCA认证考试指南全册:Oracle Database 11g(1Z0-051,1Z0-052,1Z0-053)--详细书签版(第2/2部分)

    6.1.2 身份验证方法 170 6.1.3 创建账户 173 6.2 授予和撤销权限 176 6.2.1 系统权限 176 6.2.2 对象权限 178 6.3 创建和管理角色 182 6.3.1 创建角色并授予角色权限 182 6.3.2 预先定义的角色 183 6.3.3 ...

    OCPOCA认证考试指南全册:Oracle Database 11g(1Z0-051,1Z0-052,1Z0-053)--详细书签版(第1/2部分)

    6.1.2 身份验证方法 170 6.1.3 创建账户 173 6.2 授予和撤销权限 176 6.2.1 系统权限 176 6.2.2 对象权限 178 6.3 创建和管理角色 182 6.3.1 创建角色并授予角色权限 182 6.3.2 预先定义的角色 183 6.3.3 ...

    Windows内核安全与驱动开发光盘源码

    13.3.1 建立通信端口的方法 310 13.3.2 在用户态通过DLL使用通信端口的范例 311 13.4 Minifilter的安装与加载 314 13.4.1 安装Minifilter的INF文件 314 13.4.2 启动安装完成的Minifilter 316 第14章 网络传输层...

    Windows内核安全驱动开发(随书光盘)

    13.3.1 建立通信端口的方法 310 13.3.2 在用户态通过DLL使用通信端口的范例 311 13.4 Minifilter的安装与加载 314 13.4.1 安装Minifilter的INF文件 314 13.4.2 启动安装完成的Minifilter 316 第14章 网络传输层...

    网管教程 从入门到精通软件篇.txt

    IVD:超过20/20微观数据维数或变量等级文件 IVP:超过20/20的用户子集配置文件 IVT:超过20/20表或集合数据文件 IVX:超过20/20微数据目录文件 IW:Idlewild屏幕保护程序 IWC:Install Watch文档 J J62:...

Global site tag (gtag.js) - Google Analytics