?? rarvm.java
字號:
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 31.05.2007
*
* Source: $HeadURL$
* Last changed: $LastChangedDate$
*
* the unrar licence applies to all junrar source and binary distributions
* you are not allowed to use this source to re-create the RAR compression algorithm
*
* Here some html entities which can be used for escaping javadoc tags:
* "&": "&" or "&"
* "<": "<" or "<"
* ">": ">" or ">"
* "@": "@"
*/
package de.innosystec.unrar.unpack.vm;
import java.util.List;
import java.util.Vector;
import de.innosystec.unrar.crc.RarCRC;
import de.innosystec.unrar.io.Raw;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class RarVM extends BitInput {
public static final int VM_MEMSIZE = 0x40000;
public static final int VM_MEMMASK = (VM_MEMSIZE - 1);
public static final int VM_GLOBALMEMADDR = 0x3C000;
public static final int VM_GLOBALMEMSIZE = 0x2000;
public static final int VM_FIXEDGLOBALSIZE = 64;
private static final int regCount = 8;
private static final long UINT_MASK = 0xffffFFFF;//((long)2*(long)Integer.MAX_VALUE);
private byte[] mem;
private int[] R = new int[regCount];
private int flags;
private int maxOpCount = 25000000;
private int codeSize;
private int IP;
public RarVM() {
mem = null;
}
public void init() {
if (mem == null) {
mem = new byte[VM_MEMSIZE + 4];
}
}
private boolean isVMMem(byte[] mem) {
return this.mem == mem;
}
private int getValue(boolean byteMode, byte[] mem, int offset) {
if (byteMode) {
if (isVMMem(mem)) {
return (mem[offset]);
} else {
return (mem[offset] & 0xff);
}
} else {
if (isVMMem(mem)) {
//little
return Raw.readIntLittleEndian(mem, offset);
} else
//big endian
return Raw.readIntBigEndian(mem, offset);
}
}
private void setValue(boolean byteMode, byte[] mem, int offset, int value) {
if (byteMode) {
if (isVMMem(mem)) {
mem[offset] = (byte) value;
} else {
mem[offset] = (byte) ((mem[offset] & 0x00) | (byte) (value & 0xff));
}
} else {
if (isVMMem(mem)) {
Raw.writeIntLittleEndian(mem, offset, value);
// mem[offset + 0] = (byte) value;
// mem[offset + 1] = (byte) (value >>> 8);
// mem[offset + 2] = (byte) (value >>> 16);
// mem[offset + 3] = (byte) (value >>> 24);
} else {
Raw.writeIntBigEndian(mem, offset, value);
// mem[offset + 3] = (byte) value;
// mem[offset + 2] = (byte) (value >>> 8);
// mem[offset + 1] = (byte) (value >>> 16);
// mem[offset + 0] = (byte) (value >>> 24);
}
}
// #define SET_VALUE(ByteMode,Addr,Value) SetValue(ByteMode,(uint
// *)Addr,Value)
}
public void setLowEndianValue(byte[] mem, int offset, int value) {
Raw.writeIntLittleEndian(mem, offset, value);
// mem[offset + 0] = (byte) (value&0xff);
// mem[offset + 1] = (byte) ((value >>> 8)&0xff);
// mem[offset + 2] = (byte) ((value >>> 16)&0xff);
// mem[offset + 3] = (byte) ((value >>> 24)&0xff);
}
public void setLowEndianValue(Vector<Byte> mem, int offset, int value) {
mem.set(offset + 0, Byte.valueOf((byte) (value&0xff))) ;
mem.set(offset + 1, Byte.valueOf((byte) ((value >>> 8)&0xff)));
mem.set(offset + 2, Byte.valueOf((byte) ((value >>> 16)&0xff) ));
mem.set(offset + 3, Byte.valueOf((byte) ((value >>> 24)&0xff))) ;
}
private int getOperand(VMPreparedOperand cmdOp) {
int ret = 0;
if (cmdOp.getType() == VMOpType.VM_OPREGMEM) {
int pos = (cmdOp.getOffset() + cmdOp.getBase()) & VM_MEMMASK;
ret = Raw.readIntLittleEndian(mem, pos);
} else {
int pos = cmdOp.getOffset();
ret = Raw.readIntLittleEndian(mem, pos);
}
return ret;
}
public void execute(VMPreparedProgram prg) {
for (int i = 0; i < prg.getInitR().length; i++) // memcpy(R,Prg->InitR,sizeof(Prg->InitR));
{
R[i] = prg.getInitR()[i];
}
long globalSize = Math
.min(prg.getGlobalData().size(), VM_GLOBALMEMSIZE) & 0xffFFffFF;
if (globalSize != 0) {
for (int i = 0; i < globalSize; i++) // memcpy(Mem+VM_GLOBALMEMADDR,&Prg->GlobalData[0],GlobalSize);
{
mem[VM_GLOBALMEMADDR + i] = prg.getGlobalData().get(i);
}
}
long staticSize = Math.min(prg.getStaticData().size(), VM_GLOBALMEMSIZE
- globalSize) & 0xffFFffFF;
if (staticSize != 0) {
for (int i = 0; i < staticSize; i++) // memcpy(Mem+VM_GLOBALMEMADDR+GlobalSize,&Prg->StaticData[0],StaticSize);
{
mem[VM_GLOBALMEMADDR + (int) globalSize + i] = prg
.getStaticData().get(i);
}
}
R[7] = VM_MEMSIZE;
flags = 0;
List<VMPreparedCommand> preparedCode = prg.getAltCmd().size() != 0 ? prg
.getAltCmd()
: prg.getCmd();
if (!ExecuteCode(preparedCode, prg.getCmdCount())) {
preparedCode.get(0).setOpCode(VMCommands.VM_RET);
}
int newBlockPos = getValue(false, mem, VM_GLOBALMEMADDR + 0x20)
& VM_MEMMASK;
int newBlockSize = getValue(false, mem, VM_GLOBALMEMADDR + 0x1c)
& VM_MEMMASK;
if ((newBlockPos + newBlockSize) >= VM_MEMSIZE) {
newBlockPos = 0;
newBlockSize = 0;
}
prg.setFilteredDataOffset(newBlockPos);
prg.setFilteredDataSize(newBlockSize);
prg.getGlobalData().clear();
int dataSize = Math.min(getValue(false, mem, VM_GLOBALMEMADDR + 0x30),
VM_GLOBALMEMSIZE - VM_FIXEDGLOBALSIZE);
if (dataSize != 0) {
prg.getGlobalData().setSize(dataSize + VM_FIXEDGLOBALSIZE);
// ->GlobalData.Add(dataSize+VM_FIXEDGLOBALSIZE);
for (int i = 0; i < dataSize + VM_FIXEDGLOBALSIZE; i++) // memcpy(&Prg->GlobalData[0],&Mem[VM_GLOBALMEMADDR],DataSize+VM_FIXEDGLOBALSIZE);
{
prg.getGlobalData().set(i, mem[VM_GLOBALMEMADDR + i]);
}
}
}
public byte[] getMem()
{
return mem;
}
private boolean setIP(int ip) {
if ((ip) >= codeSize) {
return (true);
}
if (--maxOpCount <= 0) {
return (false);
}
IP = ip;
return true;
}
private boolean ExecuteCode(List<VMPreparedCommand> preparedCode,
int cmdCount) {
maxOpCount = 25000000;
this.codeSize = cmdCount;
this.IP = 0;
while (true) {
VMPreparedCommand cmd = preparedCode.get(IP);
int op1 = getOperand(cmd.getOp1());
int op2 = getOperand(cmd.getOp2());
switch (cmd.getOpCode()) {
case VM_MOV:
setValue(cmd.isByteMode(), mem, op1, getValue(cmd.isByteMode(),
mem, op2)); // SET_VALUE(Cmd->ByteMode,Op1,GET_VALUE(Cmd->ByteMode,Op2));
break;
case VM_MOVB:
setValue(true, mem, op1, getValue(true, mem, op2));
break;
case VM_MOVD:
setValue(false, mem, op1, getValue(false, mem, op2));
break;
case VM_CMP: {
int value1 = getValue(cmd.isByteMode(), mem, op1);
int result = value1 - getValue(cmd.isByteMode(), mem, op2);
if (result == 0) {
flags = VMFlags.VM_FZ.getFlag();
} else {
flags = (result > value1) ? 1 : 0 | (result & VMFlags.VM_FS
.getFlag());
}
}
break;
case VM_CMPB: {
int value1 = getValue(true, mem, op1);
int result = value1 - getValue(true, mem, op2);
if (result == 0) {
flags = VMFlags.VM_FZ.getFlag();
} else {
flags = (result > value1) ? 1 : 0 | (result & VMFlags.VM_FS
.getFlag());
}
}
break;
case VM_CMPD: {
int value1 = getValue(false, mem, op1);
int result = value1 - getValue(false, mem, op2);
if (result == 0) {
flags = VMFlags.VM_FZ.getFlag();
} else {
flags = (result > value1) ? 1 : 0 | (result & VMFlags.VM_FS
.getFlag());
}
}
break;
case VM_ADD: {
int value1 = getValue(cmd.isByteMode(), mem, op1);
int result = (int) ((((long) value1 + (long) getValue(cmd
.isByteMode(), mem, op2))) & 0xffffffff);
if (cmd.isByteMode()) {
result &= 0xff;
flags = (result < value1) ? 1
: 0 | (result == 0 ? VMFlags.VM_FZ.getFlag()
: ((result & 0x80) != 0) ? VMFlags.VM_FS
.getFlag() : 0);
// Flags=(Result<Value1)|(Result==0 ? VM_FZ:((Result&0x80) ?
// VM_FS:0));
} else
flags = (result < value1) ? 1
: 0 | (result == 0 ? VMFlags.VM_FZ.getFlag()
: (result & VMFlags.VM_FS.getFlag()));
setValue(cmd.isByteMode(), mem, op1, result);
}
break;
case VM_ADDB:
setValue(true, mem, op1,
(int) ((long) getValue(true, mem, op1) & 0xFFffFFff
+ (long) getValue(true, mem, op2) & 0xFFffFFff));
break;
case VM_ADDD:
setValue(
false,
mem,
op1,
(int) ((long) getValue(false, mem, op1) & 0xFFffFFff
+ (long) getValue(false, mem, op2) & 0xFFffFFff));
break;
case VM_SUB: {
int value1 = getValue(cmd.isByteMode(), mem, op1);
int result = (int) ((long) value1 & 0xffFFffFF
- (long) getValue(cmd.isByteMode(), mem, op2) & 0xFFffFFff);
flags = (result == 0) ? VMFlags.VM_FZ.getFlag()
: (result > value1) ? 1 : 0 | (result & VMFlags.VM_FS
.getFlag());
setValue(cmd.isByteMode(), mem, op1, result);// (Cmd->ByteMode,Op1,Result);
}
break;
case VM_SUBB:
setValue(true, mem, op1,
(int) ((long) getValue(true, mem, op1) & 0xFFffFFff
- (long) getValue(true, mem, op2) & 0xFFffFFff));
break;
case VM_SUBD:
setValue(
false,
mem,
op1,
(int) ((long) getValue(false, mem, op1) & 0xFFffFFff
- (long) getValue(false, mem, op2) & 0xFFffFFff));
break;
case VM_JZ:
if ((flags & VMFlags.VM_FZ.getFlag()) != 0) {
setIP(getValue(false, mem, op1));
continue;
}
break;
case VM_JNZ:
if ((flags & VMFlags.VM_FZ.getFlag()) == 0) {
setIP(getValue(false, mem, op1));
continue;
}
break;
case VM_INC: {
int result = (int) ((long) getValue(cmd.isByteMode(), mem, op1) & 0xFFffFFff + 1);
if (cmd.isByteMode()) {
result &= 0xff;
}
setValue(cmd.isByteMode(), mem, op1, result);
flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result
& VMFlags.VM_FS.getFlag();
}
break;
case VM_INCB:
setValue(
true,
mem,
op1,
(int) ((long) getValue(true, mem, op1) & 0xFFffFFff + 1));
break;
case VM_INCD:
setValue(false, mem, op1, (int) ((long) getValue(false, mem,
op1) & 0xFFffFFff + 1));
break;
case VM_DEC: {
int result = (int) ((long) getValue(cmd.isByteMode(), mem, op1) & 0xFFffFFff - 1);
setValue(cmd.isByteMode(), mem, op1, result);
flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result
& VMFlags.VM_FS.getFlag();
}
break;
case VM_DECB:
setValue(
true,
mem,
op1,
(int) ((long) getValue(true, mem, op1) & 0xFFffFFff - 1));
break;
case VM_DECD:
setValue(false, mem, op1, (int) ((long) getValue(false, mem,
op1) & 0xFFffFFff - 1));
break;
case VM_JMP:
setIP(getValue(false, mem, op1));
continue;
case VM_XOR: {
int result = getValue(cmd.isByteMode(), mem, op1)
^ getValue(cmd.isByteMode(), mem, op2);
flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result
& VMFlags.VM_FS.getFlag();
setValue(cmd.isByteMode(), mem, op1, result);
}
break;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -