/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.dexbacked;
import org.jf.util.ExceptionWithContext;
import org.jf.util.Utf8Utils;
import javax.annotation.Nonnull;
public class BaseDexReader<T extends BaseDexBuffer> {
@Nonnull
public final T dexBuf;
private int offset;
public BaseDexReader(@Nonnull T dexBuf, int offset) {
this.dexBuf = dexBuf;
this.offset = offset;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
/** {@inheritDoc} */
public int readSleb128() {
if (dexBuf.getReader() == null) {
int end = offset;
int currentByteValue;
int result;
byte[] buf = dexBuf.buf;
result = buf[end++] & 0xff;
if (result <= 0x7f) {
result = (result << 25) >> 25;
} else {
currentByteValue = buf[end++] & 0xff;
result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
if (currentByteValue <= 0x7f) {
result = (result << 18) >> 18;
} else {
currentByteValue = buf[end++] & 0xff;
result |= (currentByteValue & 0x7f) << 14;
if (currentByteValue <= 0x7f) {
result = (result << 11) >> 11;
} else {
currentByteValue = buf[end++] & 0xff;
result |= (currentByteValue & 0x7f) << 21;
if (currentByteValue <= 0x7f) {
result = (result << 4) >> 4;
} else {
currentByteValue = buf[end++] & 0xff;
if (currentByteValue > 0x7f) {
throw new ExceptionWithContext(
"Invalid sleb128 integer encountered at offset 0x%x",
offset);
}
result |= currentByteValue << 28;
}
}
}
}
offset = end;
return result;
} else {
int end = offset;
int currentByteValue;
int result;
result = dexBuf.getReader()
.readBytes(dexBuf.getBaseAddr() + end, 1)[0] & 0xff;
end++;
if (result <= 0x7f) {
result = (result << 25) >> 25;
} else {
currentByteValue = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + end, 1)[0] & 0xff;
end++;
result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
if (currentByteValue <= 0x7f) {
result = (result << 18) >> 18;
} else {
currentByteValue = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + end, 1)[0] & 0xff;
end++;
result |= (currentByteValue & 0x7f) << 14;
if (currentByteValue <= 0x7f) {
result = (result << 11) >> 11;
} else {
currentByteValue = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + end, 1)[0] & 0xff;
end++;
result |= (currentByteValue & 0x7f) << 21;
if (currentByteValue <= 0x7f) {
result = (result << 4) >> 4;
} else {
currentByteValue = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + end, 1)[0] & 0xff;
end++;
if (currentByteValue > 0x7f) {
throw new ExceptionWithContext(
"Invalid sleb128 integer encountered at offset 0x%x",
offset);
}
result |= currentByteValue << 28;
}
}
}
}
offset = end;
return result;
}
}
public int readSmallUleb128() {
return readUleb128(false);
}
private int readUleb128(boolean allowLarge) {
if (this.dexBuf.getReader() == null) {
int end = offset;
int currentByteValue;
int result;
byte[] buf = dexBuf.buf;
result = buf[end++] & 0xff;
if (result > 0x7f) {
currentByteValue = buf[end++] & 0xff;
result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
if (currentByteValue > 0x7f) {
currentByteValue = buf[end++] & 0xff;
result |= (currentByteValue & 0x7f) << 14;
if (currentByteValue > 0x7f) {
currentByteValue = buf[end++] & 0xff;
result |= (currentByteValue & 0x7f) << 21;
if (currentByteValue > 0x7f) {
currentByteValue = buf[end++];
// MSB shouldn't be set on last byte
if (currentByteValue < 0) {
throw new ExceptionWithContext(
"Invalid uleb128 integer encountered at offset 0x%x",
offset);
} else if ((currentByteValue & 0xf) > 0x07) {
if (!allowLarge) {
// for non-large uleb128s, we assume most
// significant bit of the result will not be
// set, so that it can fit into a signed
// integer
// without wrapping
throw new ExceptionWithContext(
"Encountered valid uleb128 that is out of range at offset 0x%x",
offset);
}
}
result |= currentByteValue << 28;
}
}
}
}
offset = end;
return result;
} else {
int end = offset;
int currentByteValue;
int result;
result = dexBuf.getReader()
.readBytes(dexBuf.getBaseAddr() + end, 1)[0] & 0xff;
end++;
if (result > 0x7f) {
currentByteValue = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + end, 1)[0] & 0xff;
end++;
result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
if (currentByteValue > 0x7f) {
currentByteValue = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + end, 1)[0] & 0xff;
end++;
result |= (currentByteValue & 0x7f) << 14;
if (currentByteValue > 0x7f) {
currentByteValue = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + end, 1)[0] & 0xff;
end++;
result |= (currentByteValue & 0x7f) << 21;
if (currentByteValue > 0x7f) {
currentByteValue = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + end, 1)[0];
end++;
// MSB shouldn't be set on last byte
if (currentByteValue < 0) {
throw new ExceptionWithContext(
"Invalid uleb128 integer encountered at offset 0x%x",
offset);
} else if ((currentByteValue & 0xf) > 0x07) {
if (!allowLarge) {
// for non-large uleb128s, we assume most
// significant bit of the result will not be
// set, so that it can fit into a signed
// integer
// without wrapping
throw new ExceptionWithContext(
"Encountered valid uleb128 that is out of range at offset 0x%x",
offset);
}
}
result |= currentByteValue << 28;
}
}
}
}
offset = end;
return result;
}
}
/**
* Reads a "large" uleb128. That is, one that may legitimately be greater
* than a signed int.
*
* The value is returned as if it were signed. i.e. a value of 0xFFFFFFFF
* would be returned as -1. It is up to the caller to handle the value
* appropriately.
*/
public int readLargeUleb128() {
return readUleb128(true);
}
/**
* Reads a "big" uleb128 that can legitimately be > 2^31. The value is
* returned as a signed integer, with the expected semantics of
* re-interpreting an unsigned value as a signed value.
*
* @return The unsigned value, reinterpreted as a signed int
*/
public int readBigUleb128() {
if (this.dexBuf.getReader() == null) {
int end = offset;
int currentByteValue;
int result;
byte[] buf = dexBuf.buf;
result = buf[end++] & 0xff;
if (result > 0x7f) {
currentByteValue = buf[end++] & 0xff;
result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
if (currentByteValue > 0x7f) {
currentByteValue = buf[end++] & 0xff;
result |= (currentByteValue & 0x7f) << 14;
if (currentByteValue > 0x7f) {
currentByteValue = buf[end++] & 0xff;
result |= (currentByteValue & 0x7f) << 21;
if (currentByteValue > 0x7f) {
currentByteValue = buf[end++];
// MSB shouldn't be set on last byte
if (currentByteValue < 0) {
throw new ExceptionWithContext(
"Invalid uleb128 integer encountered at offset 0x%x",
offset);
}
result |= currentByteValue << 28;
}
}
}
}
offset = end;
return result;
} else {
int end = offset;
int currentByteValue;
int result;
result = dexBuf.getReader()
.readBytes(dexBuf.getBaseAddr() + end, 1)[0] & 0xff;
end++;
if (result > 0x7f) {
currentByteValue = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + end, 1)[0] & 0xff;
end++;
result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
if (currentByteValue > 0x7f) {
currentByteValue = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + end, 1)[0] & 0xff;
end++;
result |= (currentByteValue & 0x7f) << 14;
if (currentByteValue > 0x7f) {
currentByteValue = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + end, 1)[0] & 0xff;
end++;
result |= (currentByteValue & 0x7f) << 21;
if (currentByteValue > 0x7f) {
currentByteValue = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + end, 1)[0];
end++;
// MSB shouldn't be set on last byte
if (currentByteValue < 0) {
throw new ExceptionWithContext(
"Invalid uleb128 integer encountered at offset 0x%x",
offset);
}
result |= currentByteValue << 28;
}
}
}
}
offset = end;
return result;
}
}
public void skipUleb128() {
if (this.dexBuf.getReader() == null) {
int end = offset;
byte currentByteValue;
byte[] buf = dexBuf.buf;
currentByteValue = buf[end++];
if (currentByteValue < 0) { // if the MSB is set
currentByteValue = buf[end++];
if (currentByteValue < 0) { // if the MSB is set
currentByteValue = buf[end++];
if (currentByteValue < 0) { // if the MSB is set
currentByteValue = buf[end++];
if (currentByteValue < 0) { // if the MSB is set
currentByteValue = buf[end++];
if (currentByteValue < 0) {
throw new ExceptionWithContext(
"Invalid uleb128 integer encountered at offset 0x%x",
offset);
}
}
}
}
}
offset = end;
} else {
int end = offset;
byte currentByteValue;
currentByteValue = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + end, 1)[0];
end++;
if (currentByteValue < 0) { // if the MSB is set
currentByteValue = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + end, 1)[0];
end++;
if (currentByteValue < 0) { // if the MSB is set
currentByteValue = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + end, 1)[0];
end++;
if (currentByteValue < 0) { // if the MSB is set
currentByteValue = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + end, 1)[0];
end++;
if (currentByteValue < 0) { // if the MSB is set
currentByteValue = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + end, 1)[0];
end++;
if (currentByteValue < 0) {
throw new ExceptionWithContext(
"Invalid uleb128 integer encountered at offset 0x%x",
offset);
}
}
}
}
}
offset = end;
}
}
public int readSmallUint() {
int o = offset;
int result = dexBuf.readSmallUint(o);
offset = o + 4;
return result;
}
public int readOptionalUint() {
int o = offset;
int result = dexBuf.readOptionalUint(o);
offset = o + 4;
return result;
}
public int peekUshort() {
return dexBuf.readUshort(offset);
}
public int readUshort() {
int o = offset;
int result = dexBuf.readUshort(offset);
offset = o + 2;
return result;
}
public int peekUbyte() {
return dexBuf.readUbyte(offset);
}
public int readUbyte() {
int o = offset;
int result = dexBuf.readUbyte(offset);
offset = o + 1;
return result;
}
public long readLong() {
int o = offset;
long result = dexBuf.readLong(offset);
offset = o + 8;
return result;
}
public int readInt() {
int o = offset;
int result = dexBuf.readInt(offset);
offset = o + 4;
return result;
}
public int readShort() {
int o = offset;
int result = dexBuf.readShort(offset);
offset = o + 2;
return result;
}
public int readByte() {
int o = offset;
int result = dexBuf.readByte(offset);
offset = o + 1;
return result;
}
public void skipByte() {
offset++;
}
public void moveRelative(int i) {
offset += i;
}
public int readSmallUint(int offset) {
return dexBuf.readSmallUint(offset);
}
public int readUshort(int offset) {
return dexBuf.readUshort(offset);
}
public int readUbyte(int offset) {
return dexBuf.readUbyte(offset);
}
public long readLong(int offset) {
return dexBuf.readLong(offset);
}
public int readInt(int offset) {
return dexBuf.readInt(offset);
}
public int readShort(int offset) {
return dexBuf.readShort(offset);
}
public int readByte(int offset) {
return dexBuf.readByte(offset);
}
public int readSizedInt(int bytes) {
if (this.dexBuf.getReader() == null) {
int o = offset;
byte[] buf = dexBuf.buf;
int result;
switch (bytes) {
case 4:
result = (buf[o] & 0xff) | ((buf[o + 1] & 0xff) << 8)
| ((buf[o + 2] & 0xff) << 16) | (buf[o + 3] << 24);
break;
case 3:
result = (buf[o] & 0xff) | ((buf[o + 1] & 0xff) << 8)
| ((buf[o + 2]) << 16);
break;
case 2:
result = (buf[o] & 0xff) | ((buf[o + 1]) << 8);
break;
case 1:
result = buf[o];
break;
default:
throw new ExceptionWithContext(
"Invalid size %d for sized int at offset 0x%x", bytes,
offset);
}
offset = o + bytes;
return result;
} else {
int o = offset;
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o, bytes);
int result;
switch (bytes) {
case 4:{
result = (buf[0] & 0xff) | ((buf[1] & 0xff) << 8)
| ((buf[2] & 0xff) << 16) | (buf[3] << 24);
break;
}
case 3:{
result = (buf[0] & 0xff) | ((buf[1] & 0xff) << 8)
| ((buf[2]) << 16);
break;
}
case 2:{
result = (buf[0] & 0xff) | ((buf[1]) << 8);
break;
}
case 1:{
result = buf[0];
break;
}
default:
throw new ExceptionWithContext(
"Invalid size %d for sized int at offset 0x%x", bytes,
offset);
}
offset = o + bytes;
return result;
}
}
public int readSizedSmallUint(int bytes) {
if (this.dexBuf.getReader() == null) {
int o = offset;
byte[] buf = dexBuf.buf;
int result = 0;
switch (bytes) {
case 4:
int b = buf[o + 3];
if (b < 0) {
throw new ExceptionWithContext(
"Encountered valid sized uint that is out of range at offset 0x%x",
offset);
}
result = b << 24;
// fall-through
case 3:
result |= (buf[o + 2] & 0xff) << 16;
// fall-through
case 2:
result |= (buf[o + 1] & 0xff) << 8;
// fall-through
case 1:
result |= (buf[o] & 0xff);
break;
default:
throw new ExceptionWithContext(
"Invalid size %d for sized uint at offset 0x%x", bytes,
offset);
}
offset = o + bytes;
return result;
} else {
int o = offset;
byte[] buf = null;
buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,bytes);
int result = 0;
switch (bytes) {
case 4:{
int b = buf[3];
if (b < 0) {
throw new ExceptionWithContext(
"Encountered valid sized uint that is out of range at offset 0x%x",
offset);
}
result = b << 24;
}
// fall-through
case 3:{
result |= (buf[2] & 0xff) << 16;
}
// fall-through
case 2:{
result |= (buf[1] & 0xff) << 8;
}
// fall-through
case 1:{
result |= (buf[0] & 0xff);
break;
}
default:
throw new ExceptionWithContext(
"Invalid size %d for sized uint at offset 0x%x", bytes,
offset);
}
offset = o + bytes;
return result;
}
}
public int readSizedRightExtendedInt(int bytes) {
if (this.dexBuf.getReader() == null) {
int o = offset;
byte[] buf = dexBuf.buf;
int result;
switch (bytes) {
case 4:
result = (buf[o] & 0xff) | ((buf[o + 1] & 0xff) << 8)
| ((buf[o + 2] & 0xff) << 16) | (buf[o + 3] << 24);
break;
case 3:
result = (buf[o] & 0xff) << 8 | ((buf[o + 1] & 0xff) << 16)
| (buf[o + 2] << 24);
break;
case 2:
result = (buf[o] & 0xff) << 16 | (buf[o + 1] << 24);
break;
case 1:
result = buf[o] << 24;
break;
default:
throw new ExceptionWithContext(
"Invalid size %d for sized, right extended int at offset 0x%x",
bytes, offset);
}
offset = o + bytes;
return result;
} else {
int o = offset;
int result;
switch (bytes) {
case 4:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,4);
result = (buf[0] & 0xff) | ((buf[1] & 0xff) << 8)
| ((buf[2] & 0xff) << 16) | (buf[3] << 24);
break;
}
case 3:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,3);
result = (buf[0] & 0xff) << 8 | ((buf[1] & 0xff) << 16)
| (buf[2] << 24);
break;
}
case 2:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,2);
result = (buf[0] & 0xff) << 16 | (buf[1] << 24);
break;
}
case 1:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,1);
result = buf[0] << 24;
break;
}
default:
throw new ExceptionWithContext(
"Invalid size %d for sized, right extended int at offset 0x%x",
bytes, offset);
}
offset = o + bytes;
return result;
}
}
public long readSizedRightExtendedLong(int bytes) {
if (this.dexBuf.getReader() == null) {
int o = offset;
byte[] buf = dexBuf.buf;
long result;
switch (bytes) {
case 8:
result = (buf[o] & 0xff) | ((buf[o + 1] & 0xff) << 8)
| ((buf[o + 2] & 0xff) << 16)
| ((buf[o + 3] & 0xffL) << 24)
| ((buf[o + 4] & 0xffL) << 32)
| ((buf[o + 5] & 0xffL) << 40)
| ((buf[o + 6] & 0xffL) << 48)
| (((long) buf[o + 7]) << 56);
break;
case 7:
result = ((buf[o] & 0xff)) << 8 | ((buf[o + 1] & 0xff) << 16)
| ((buf[o + 2] & 0xffL) << 24)
| ((buf[o + 3] & 0xffL) << 32)
| ((buf[o + 4] & 0xffL) << 40)
| ((buf[o + 5] & 0xffL) << 48)
| (((long) buf[o + 6]) << 56);
break;
case 6:
result = ((buf[o] & 0xff)) << 16 | ((buf[o + 1] & 0xffL) << 24)
| ((buf[o + 2] & 0xffL) << 32)
| ((buf[o + 3] & 0xffL) << 40)
| ((buf[o + 4] & 0xffL) << 48)
| (((long) buf[o + 5]) << 56);
break;
case 5:
result = ((buf[o] & 0xffL)) << 24
| ((buf[o + 1] & 0xffL) << 32)
| ((buf[o + 2] & 0xffL) << 40)
| ((buf[o + 3] & 0xffL) << 48)
| (((long) buf[o + 4]) << 56);
break;
case 4:
result = ((buf[o] & 0xffL)) << 32
| ((buf[o + 1] & 0xffL) << 40)
| ((buf[o + 2] & 0xffL) << 48)
| (((long) buf[o + 3]) << 56);
break;
case 3:
result = ((buf[o] & 0xffL)) << 40
| ((buf[o + 1] & 0xffL) << 48)
| (((long) buf[o + 2]) << 56);
break;
case 2:
result = ((buf[o] & 0xffL)) << 48 | (((long) buf[o + 1]) << 56);
break;
case 1:
result = ((long) buf[o]) << 56;
break;
default:
throw new ExceptionWithContext(
"Invalid size %d for sized, right extended long at offset 0x%x",
bytes, offset);
}
offset = o + bytes;
return result;
} else {
int o = offset;
long result;
switch (bytes) {
case 8:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,8);
result = (buf[0] & 0xff) | ((buf[1] & 0xff) << 8)
| ((buf[2] & 0xff) << 16) | ((buf[3] & 0xffL) << 24)
| ((buf[4] & 0xffL) << 32) | ((buf[5] & 0xffL) << 40)
| ((buf[6] & 0xffL) << 48) | (((long) buf[7]) << 56);
break;
}
case 7:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,7);
result = ((buf[0] & 0xff)) << 8 | ((buf[1] & 0xff) << 16)
| ((buf[2] & 0xffL) << 24) | ((buf[3] & 0xffL) << 32)
| ((buf[4] & 0xffL) << 40) | ((buf[5] & 0xffL) << 48)
| (((long) buf[6]) << 56);
break;
}
case 6: {
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,6);
result = ((buf[0] & 0xff)) << 16 | ((buf[1] & 0xffL) << 24)
| ((buf[2] & 0xffL) << 32) | ((buf[3] & 0xffL) << 40)
| ((buf[4] & 0xffL) << 48) | (((long) buf[5]) << 56);
break;
}
case 5:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,5);
result = ((buf[0] & 0xffL)) << 24 | ((buf[1] & 0xffL) << 32)
| ((buf[2] & 0xffL) << 40) | ((buf[3] & 0xffL) << 48)
| (((long) buf[4]) << 56);
break;
}
case 4:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,4);
result = ((buf[0] & 0xffL)) << 32 | ((buf[1] & 0xffL) << 40)
| ((buf[2] & 0xffL) << 48) | (((long) buf[3]) << 56);
break;
}
case 3:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,3);
result = ((buf[0] & 0xffL)) << 40 | ((buf[1] & 0xffL) << 48)
| (((long) buf[2]) << 56);
break;
}
case 2:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,2);
result = ((buf[0] & 0xffL)) << 48 | (((long) buf[1]) << 56);
break;
}
case 1:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,1);
result = ((long) buf[0]) << 56;
break;
}
default:
throw new ExceptionWithContext(
"Invalid size %d for sized, right extended long at offset 0x%x",
bytes, offset);
}
offset = o + bytes;
return result;
}
}
public long readSizedLong(int bytes) {
if (this.dexBuf.getReader() == null) {
int o = offset;
byte[] buf = dexBuf.buf;
long result;
switch (bytes) {
case 8:
result = (buf[o] & 0xff) | ((buf[o + 1] & 0xff) << 8)
| ((buf[o + 2] & 0xff) << 16)
| ((buf[o + 3] & 0xffL) << 24)
| ((buf[o + 4] & 0xffL) << 32)
| ((buf[o + 5] & 0xffL) << 40)
| ((buf[o + 6] & 0xffL) << 48)
| (((long) buf[o + 7]) << 56);
break;
case 7:
result = (buf[o] & 0xff) | ((buf[o + 1] & 0xff) << 8)
| ((buf[o + 2] & 0xff) << 16)
| ((buf[o + 3] & 0xffL) << 24)
| ((buf[o + 4] & 0xffL) << 32)
| ((buf[o + 5] & 0xffL) << 40)
| ((long) (buf[o + 6]) << 48);
break;
case 6:
result = (buf[o] & 0xff) | ((buf[o + 1] & 0xff) << 8)
| ((buf[o + 2] & 0xff) << 16)
| ((buf[o + 3] & 0xffL) << 24)
| ((buf[o + 4] & 0xffL) << 32)
| ((long) (buf[o + 5]) << 40);
break;
case 5:
result = (buf[o] & 0xff) | ((buf[o + 1] & 0xff) << 8)
| ((buf[o + 2] & 0xff) << 16)
| ((buf[o + 3] & 0xffL) << 24)
| ((long) (buf[o + 4]) << 32);
break;
case 4:
result = (buf[o] & 0xff) | ((buf[o + 1] & 0xff) << 8)
| ((buf[o + 2] & 0xff) << 16)
| (((long) buf[o + 3]) << 24);
break;
case 3:
result = (buf[o] & 0xff) | ((buf[o + 1] & 0xff) << 8)
| (buf[o + 2] << 16);
break;
case 2:
result = (buf[o] & 0xff) | (buf[o + 1] << 8);
break;
case 1:
result = buf[o];
break;
default:
throw new ExceptionWithContext(
"Invalid size %d for sized long at offset 0x%x", bytes,
offset);
}
offset = o + bytes;
return result;
} else {
int o = offset;
long result;
switch (bytes) {
case 8:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,8);
result = (buf[0] & 0xff) | ((buf[1] & 0xff) << 8)
| ((buf[2] & 0xff) << 16) | ((buf[3] & 0xffL) << 24)
| ((buf[4] & 0xffL) << 32) | ((buf[5] & 0xffL) << 40)
| ((buf[6] & 0xffL) << 48) | (((long) buf[7]) << 56);
break;
}
case 7:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,7);
result = (buf[0] & 0xff) | ((buf[1] & 0xff) << 8)
| ((buf[2] & 0xff) << 16) | ((buf[3] & 0xffL) << 24)
| ((buf[4] & 0xffL) << 32) | ((buf[5] & 0xffL) << 40)
| ((long) (buf[6]) << 48);
break;
}
case 6:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,6);
result = (buf[0] & 0xff) | ((buf[1] & 0xff) << 8)
| ((buf[2] & 0xff) << 16) | ((buf[3] & 0xffL) << 24)
| ((buf[4] & 0xffL) << 32) | ((long) (buf[5]) << 40);
break;
}
case 5:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,5);
result = (buf[0] & 0xff) | ((buf[1] & 0xff) << 8)
| ((buf[2] & 0xff) << 16) | ((buf[3] & 0xffL) << 24)
| ((long) (buf[4]) << 32);
break;
}
case 4:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,4);
result = (buf[0] & 0xff) | ((buf[1] & 0xff) << 8)
| ((buf[2] & 0xff) << 16) | (((long) buf[3]) << 24);
break;
}
case 3:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,3);
result = (buf[0] & 0xff) | ((buf[1] & 0xff) << 8)
| (buf[2] << 16);
break;
}
case 2:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,2);
result = (buf[0] & 0xff) | (buf[1] << 8);
break;
}
case 1:{
byte[] buf = dexBuf.getReader().readBytes(dexBuf.getBaseAddr() + o,1);
result = buf[0];
break;
}
default:
throw new ExceptionWithContext(
"Invalid size %d for sized long at offset 0x%x", bytes,
offset);
}
offset = o + bytes;
return result;
}
}
public String readString(int utf16Length) {
if (this.dexBuf.getReader() == null) {
int[] ret = new int[1];
String value = Utf8Utils.utf8BytesWithUtf16LengthToString(
dexBuf.buf, offset, utf16Length, ret);
offset += ret[0];
return value;
} else {
int[] ret = new int[1];
byte[] buf = dexBuf.getReader().readBytes(
dexBuf.getBaseAddr() + offset, utf16Length*4);
String value = Utf8Utils.utf8BytesWithUtf16LengthToString(buf, 0,
utf16Length, ret);
offset += ret[0];
return value;
}
}
}