android dalvik浅析一

来源:互联网 发布:mac鼠标右键怎么按 编辑:程序博客网 时间:2024/05/16 10:33

     dalvik是android中使用的虚拟机,基于寄存器,分析基于android4.2源代码。本篇主要分析的是dalvik中的解释器部分,源码位于/dalvik/vm,主要代码在interp和mterp文件夹下。

     我们知道java能运行在各个平台在于它运行在虚拟机上,由虚拟机来与各个硬件平台打交道(所以说"跨平台"都是假的啰(⊙▽⊙))。则虚拟机中解释器(将字节码解释成机器码)代码必然是依赖于各平台的,且为了方便管理必定是可配置式模块化。怎么理解呢     ◔ ‸◔?  直接在android中进行分析。

..21-Nov-20124 KiB

arm-vfp/21-Nov-20124 KiB

armv5te/21-Nov-201212 KiB

armv6/21-Nov-20124 KiB

armv6t2/21-Nov-20124 KiB

armv7-a/21-Nov-20124 KiB

c/21-Nov-201212 KiB

common/21-Nov-20124 KiB

config-allstubs21-Nov-20121.4 KiB

config-armv5te21-Nov-20121.6 KiB

config-armv5te-vfp21-Nov-20123.2 KiB

config-armv7-a21-Nov-20125.2 KiB

config-armv7-a-neon21-Nov-20125.1 KiB

config-mips21-Nov-20121.7 KiB

config-portable21-Nov-20121.1 KiB

config-x8621-Nov-20121.7 KiB

cstubs/21-Nov-20124 KiB

gen-mterp.py21-Nov-201219.9 KiB

Makefile-mterp21-Nov-20121.8 KiB

mips/21-Nov-201220 KiB

Mterp.cpp21-Nov-20123 KiB

Mterp.h21-Nov-20121.3 KiB

NOTES.txt21-Nov-20123.2 KiB

out/21-Nov-20124 KiB

portable/21-Nov-20124 KiB

README.txt21-Nov-201213 KiB

rebuild.sh21-Nov-20121.1 KiB

x86/

    上面是mtero目录下代码分布,主要分析out/、gen-mterp.py、configxxx。先来看下gen-mterp.py是干什么吃的,我们知道要根据硬件平台来写解释器,当然解释器最好是能根据配置自动生成啰。 


  所谓模块化代码生成方法,就是说将解释器的实现划分成若干个模块,每一个模块都对应有一系列的输入文件(本身也是源代码文件),最后通过工具(一个Python脚本)将这些输入文件组装起来形成一个C语言文件或者汇编语言文件。这个最终得到的C语言文件或者汇编语言文件就是Dalvik虚拟机的解释器的实现文件。有了这种模块化代码生成方法之后,为某一个特定的平台生成优化过的解释器就是相当容易的:我们只需要为该平台的Dalvik虚拟机解释器的相关模块提供一个特殊版本的输入文件即可。也就是说,我们需要为每一个支持的平台提供一个配置文件,该配置文件描述了该平台的Dalvik虚拟机解释器的各个模块所要使用的输入文件。这种模块化代码生成方法不仅能避免手动编写解释器容易出错的问题,还能方便快速地将Dalvik虚拟机从一个平台移植到另外一个平台。      --by 老罗


    ok,既然这个gen-mterp.py能帮我们自动生成解释器。那我们就去一探究竟吧~( ̄▽ ̄~)(~ ̄▽ ̄)~

<span style="font-size:18px;"># ===========================================================================# "main" code# Check args.if len(sys.argv) != 3:    print "Usage: %s target-arch output-dir" % sys.argv[0]    sys.exit(2)# target-arch要生成的模式:portable fasttarget_arch = sys.argv[1]# output-dir输出目录output_dir = sys.argv[2]# Extract opcode list.# 提取dexopcode列表opcodes = getOpcodeList()# Open config file.# 打开配置文件sys.ary[1]......# Open and prepare output files.# 打开输出文件sys.ary[2]/InterpC-sys.ary[1].cpp sys.ary[2]/InterpC-sys.ary[1].stry:    c_fp = open("%s/InterpC-%s.cpp" % (output_dir, target_arch), "w")    asm_fp = open("%s/InterpAsm-%s.S" % (output_dir, target_arch), "w")except:    print "Unable to open output files"    print "Make sure directory '%s' exists and existing files are writable" \            % output_dir    # Ideally we'd remove the files to avoid confusing "make", but if they    # failed to open we probably won't be able to remove them either.    sys.exit(1)......file_header = """/* * This file was generated automatically by gen-mterp.py for '%s'. * * --> DO NOT EDIT <-- */""" % (target_arch)c_fp.write(file_header)asm_fp.write(file_header)</span>

    上面这么一大段代码究竟是干什么的呢,其实就做了2件事:

    1 在out文件夹下创建arch对应的cpp和asm解释器代码(以InterpC-armv7-a为例(以下涉及到config不再重复),会在out下创建InterpC-armv7-a.cpp和InterpAsm-armv7-a.S;看到最后的一大串字符了,你打开out下每个文件都包含);

    2 打开对应的arch配置(就是上面的一大段config-xxx文本),后面的代码就是解析这个配置文件;

    3 打开/dalvik/libdex/DexOpcodes.h 头文件,将 DEFINE_GOTO_TABLE(指令字符串)提取组成键值对(根据指令字符可到序列号)中,这个在后面构成汇编解释器时会用到

    再来看gen-mterp.py下相关的代码

<span style="font-size:18px;"># Process the config file.# 处理配置文件failed = Falsetry:# 逐行读取配置文件内容    for line in config_fp:        line = line.strip()         # remove CRLF, leading spaces        tokens = line.split(' ')    # tokenize        #print "%d: %s" % (len(tokens), tokens)        if len(tokens[0]) == 0:            #print "  blank"            pass        elif tokens[0][0] == '#':            #print "  comment"            pass        else:# 不分析空行和注释行,解析代码行            if tokens[0] == "handler-size":#  Set handler_size_bytes,二进制位数                setHandlerSize(tokens)            elif tokens[0] == "import":# 将import文件copy到输出文本:c_fp或asm_fp                importFile(tokens)            elif tokens[0] == "asm-stub":# copy asm-stub文本到asm-stub-txt                setAsmStub(tokens)            elif tokens[0] == "asm-alt-stub":# Record location of default alt stub                setAsmAltStub(tokens)            elif tokens[0] == "op-start":# in_op_start = 1 且设置default_op_dir = op-start                opStart(tokens)           ......            elif tokens[0] == "op":# 设置opcode指令的文件地址 组成键值对                opEntry(tokens)         elif tokens[0] == "handler-style":# Set interpreter style                 setHandlerStyle(tokens)          ......</span>

    上面的for ...in...语句就是在逐行解析config文本,我们只挑选重要解释:

  handler-style:设置解释器的类型

  handler-size:提到这个是因为在它需要跟 handler-style相关联,必须先设置style的值,这就关系到config文本的编写:

                                                   handler-style computed-goto

                                                   handler-size 64                                             先handler-style后handler-size


  import:直接将import的cpp和s文本写入到InterpC-armv7-a.cpp(对于cpp来说这就是全部的工作)和InterpAsm-armv7-a.S

  op-start:开始填写指令解释符,主要是设置in_op_start = 1,供下面OP 判断状态使用


  op:根据文本设置对应的opcode_locations值:op OP_ADD_DOUBLE_2ADDR armv6t2-->opcode_locations[OP_ADD_DOUBLE_2ADDR] = armv6t2 ,存储的是opcode的解释代码的文件目录,不理解看下面


  op-end:首先opcodes[index]去除opcode,然后opcode_locations[opcode]得到opcode的解释代码的文件目录Dstr,最后利用Dstr/opcode.s得到具体opcode解释代码的asm文本并将其写入InterpAsm-armv7-a.S。


   对于op-start,op,op-end举例说明:op OP_MOVE armv6t2——>op指令解析“op_mov”指令文件夹为"armv6t2",构成对应的指令解释文本为armv6t2/op_mov.s


参考资料:

生成dalvik解释器原文件的脚本:gen-mterp.py

2老罗android之旅

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小米6音量键坏了怎么办 小米2s开不开机怎么办 小米4不充电了怎么办 小米2开不开机怎么办 手机开机键开不了机怎么办 三星s4反复重启怎么办 小米5反复重启怎么办 电脑系统奔溃了怎么办 电脑开机后屏幕出现英文怎么办 小米4开不开机了怎么办 小米4一直显示mi怎么办 小米手机开关键失灵怎么办 小米手机开机键失灵怎么办 小米6不断重启怎么办 小米6一直重启怎么办 小米6自动重启怎么办 手机的开机键坏了怎么办 小米6频繁重启怎么办 小米6安装xp卡米怎么办 刷机失败反复重启怎么办 红米手机很卡怎么办啊 红米2a显示图标怎么办 手机一直处于开机状态怎么办 vivo手机进水开不了机怎么办 魅蓝s6锁了怎么办 pos机刷卡刷多了怎么办 红米5a开不机怎么办 魅族双亲要密码怎么办? 苹果wi-fi网速慢怎么办 腾达宽带用户名密码忘了怎么办 无线网秘密忘了怎么办 wan口设置已断开怎么办 中兴手机忘记解锁图案怎么办 u盘显示参数错误怎么办 硬盘vc加密密码忘了怎么办 软件文件移动到其他盘打不开怎么办 u盘无法复制文件怎么办 u盘大文件不能拷怎么办 abc看图打印不了怎么办 百度云大文件慢怎么办 手机视频缩略图加载失败怎么办