diff --git a/dex-reader/src/main/java/com/googlecode/dex2jar/reader/DexFileReader.java b/dex-reader/src/main/java/com/googlecode/dex2jar/reader/DexFileReader.java index 2af8029c..ecae30f6 100644 --- a/dex-reader/src/main/java/com/googlecode/dex2jar/reader/DexFileReader.java +++ b/dex-reader/src/main/java/com/googlecode/dex2jar/reader/DexFileReader.java @@ -48,7 +48,7 @@ public class DexFileReader { private static final byte[] DEX_FILE_MAGIC = new byte[] { 0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x35, 0x00 }; /* default */static final int ENDIAN_CONSTANT = 0x12345678; - // /* default */static final int REVERSE_ENDIAN_CONSTANT = 0x78563412; + /* default */static final int REVERSE_ENDIAN_CONSTANT = 0x78563412; private int class_defs_off; @@ -76,8 +76,8 @@ public class DexFileReader { * */ public DexFileReader(byte[] data) { - DataIn in = new DataInImpl(data); - this.in = in; + DataIn in = new EndianDataIn(data); + // { 0x64 0x65 0x78 0x0a 0x30 0x33 0x35 0x00 } = "dex\n035\0" byte[] magic = in.readBytes(8); @@ -92,10 +92,14 @@ public class DexFileReader { in.skip(4 + 20 + 4 + 4); int endian_tag = in.readUIntx(); - if (endian_tag != ENDIAN_CONSTANT) { + if (endian_tag == REVERSE_ENDIAN_CONSTANT) { + in = new ReverseEndianDataIn(data, in.getCurrentPosition()); + } else if (endian_tag != ENDIAN_CONSTANT) { throw new DexException("not support endian_tag"); } + this.in = in; + // skip uint link_size // and uint link_off // and uint map_off diff --git a/dex-reader/src/main/java/com/googlecode/dex2jar/reader/DataInImpl.java b/dex-reader/src/main/java/com/googlecode/dex2jar/reader/EndianDataIn.java similarity index 87% rename from dex-reader/src/main/java/com/googlecode/dex2jar/reader/DataInImpl.java rename to dex-reader/src/main/java/com/googlecode/dex2jar/reader/EndianDataIn.java index 9482daea..f9f510c9 100644 --- a/dex-reader/src/main/java/com/googlecode/dex2jar/reader/DataInImpl.java +++ b/dex-reader/src/main/java/com/googlecode/dex2jar/reader/EndianDataIn.java @@ -25,14 +25,19 @@ import java.util.Stack; * @author Panxiaobo [pxb1988@gmail.com] * @version $Id$ */ -/* default */class DataInImpl extends ByteArrayInputStream implements DataIn { +/* default */class EndianDataIn extends ByteArrayInputStream implements DataIn { private Stack stack = new Stack(); - public DataInImpl(byte[] data) { + public EndianDataIn(byte[] data) { super(data); } + public EndianDataIn(byte[] data, int currentPosition) { + this(data); + move(currentPosition); + } + public int getCurrentPosition() { return super.pos; } @@ -92,7 +97,7 @@ import java.util.Stack; } public int readShortx() { - return (short) (readUByte() | (readUByte() << 8)); + return (short) readUShortx(); } public int readUByte() { diff --git a/dex-reader/src/main/java/com/googlecode/dex2jar/reader/ReverseEndianDataIn.java b/dex-reader/src/main/java/com/googlecode/dex2jar/reader/ReverseEndianDataIn.java new file mode 100644 index 00000000..4e9da834 --- /dev/null +++ b/dex-reader/src/main/java/com/googlecode/dex2jar/reader/ReverseEndianDataIn.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2009-2011 Panxiaobo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.googlecode.dex2jar.reader; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.Stack; + +/** + * @see DexFileReader#ENDIAN_CONSTANT + * + * @author Panxiaobo [pxb1988@gmail.com] + * @version $Id$ + */ +/* default */class ReverseEndianDataIn extends ByteArrayInputStream implements DataIn { + + private Stack stack = new Stack(); + + public ReverseEndianDataIn(byte[] data) { + super(data); + } + + public ReverseEndianDataIn(byte[] data, int currentPosition) { + this(data); + move(currentPosition); + } + + public int getCurrentPosition() { + return super.pos; + } + + public void move(int absOffset) { + super.pos = absOffset; + } + + public void pop() { + this.move(stack.pop()); + } + + public void push() { + stack.push(super.pos); + } + + public void pushMove(int absOffset) { + this.push(); + this.move(absOffset); + } + + public int readByte() { + return (byte) super.read(); + } + + public byte[] readBytes(int size) { + byte[] data = new byte[size]; + try { + super.read(data); + } catch (IOException e) { + throw new RuntimeException(e); + } + return data; + } + + public int readIntx() { + return (super.read() << 24) | (super.read() << 16) | (super.read() << 8) | super.read(); + } + + public long readLeb128() { + int bitpos = 0; + long vln = 0L; + do { + int inp = super.read(); + vln |= ((long) (inp & 0x7F)) << bitpos; + bitpos += 7; + if ((inp & 0x80) == 0) + break; + } while (true); + if (((1L << (bitpos - 1)) & vln) != 0) + vln -= (1L << bitpos); + return vln; + } + + public long readLongx() { + return (((long) readIntx()) << 32) | (readIntx() & 0x00000000FFFFFFFFL); + } + + public int readShortx() { + return (short) readUShortx(); + } + + public int readUByte() { + return super.read(); + } + + public int readUIntx() { + return readIntx(); + } + + public long readULeb128() { + long value = 0; + int count = 0; + int b = super.read(); + while ((b & 0x80) != 0) { + value |= (b & 0x7f) << count; + count += 7; + b = super.read(); + } + value |= (b & 0x7f) << count; + return value; + } + + @Override + public int readUShortx() { + return (readUByte() << 8) | readUByte(); + } + + public void skip(int bytes) { + super.skip(bytes); + } +}