Add DexBacked implementations of the new structures

This commit is contained in:
Ben Gruver 2018-01-31 11:59:21 -08:00
parent ead2e033d0
commit dea793447f
9 changed files with 467 additions and 0 deletions

View File

@ -189,6 +189,22 @@ public class DexBackedDexFile extends BaseDexBuffer implements DexFile {
return classStartOffset + classIndex*ClassDefItem.ITEM_SIZE;
}
public int getCallSiteIdItemOffset(int callSiteIndex) {
MapItem mapItem = getMapItemForSection(ItemType.CALL_SITE_ID_ITEM);
if (mapItem == null || callSiteIndex >= mapItem.getItemCount()) {
throw new InvalidItemIndex(callSiteIndex, "Call site index out of bounds: %d", callSiteIndex);
}
return mapItem.getOffset() + callSiteIndex * CallSiteIdItem.ITEM_SIZE;
}
public int getMethodHandleItemOffset(int methodHandleIndex) {
MapItem mapItem = getMapItemForSection(ItemType.METHOD_HANDLE_ITEM);
if (mapItem == null || methodHandleIndex >= mapItem.getItemCount()) {
throw new InvalidItemIndex(methodHandleIndex , "Method handle index out of bounds: %d", methodHandleIndex);
}
return mapItem.getOffset() + methodHandleIndex * MethodHandleItem.ITEM_SIZE;
}
public int getClassCount() {
return classCount;
}
@ -213,6 +229,22 @@ public class DexBackedDexFile extends BaseDexBuffer implements DexFile {
return methodCount;
}
public int getCallSiteCount() {
MapItem mapItem = getMapItemForSection(ItemType.CALL_SITE_ID_ITEM);
if (mapItem == null) {
return 0;
}
return mapItem.getItemCount();
}
public int getMethodHandleCount() {
MapItem mapItem = getMapItemForSection(ItemType.METHOD_HANDLE_ITEM);
if (mapItem == null) {
return 0;
}
return mapItem.getItemCount();
}
@Nonnull
public String getString(int stringIndex) {
int stringOffset = getStringIdItemOffset(stringIndex);

View File

@ -0,0 +1,36 @@
/*
* Copyright 2018, 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.raw;
public class CallSiteIdItem {
public static final int ITEM_SIZE = 4;
}

View File

@ -41,6 +41,8 @@ public class ItemType {
public static final int FIELD_ID_ITEM = 0x0004;
public static final int METHOD_ID_ITEM = 0x0005;
public static final int CLASS_DEF_ITEM = 0x0006;
public static final int CALL_SITE_ID_ITEM = 0x0007;
public static final int METHOD_HANDLE_ITEM = 0x0008;
public static final int MAP_LIST = 0x1000;
public static final int TYPE_LIST = 0x1001;
public static final int ANNOTATION_SET_REF_LIST = 0x1002;
@ -63,6 +65,8 @@ public class ItemType {
case FIELD_ID_ITEM: return "field_id_item";
case METHOD_ID_ITEM: return "method_id_item";
case CLASS_DEF_ITEM: return "class_def_item";
case CALL_SITE_ID_ITEM: return "call_site_id_item";
case METHOD_HANDLE_ITEM: return "method_handle_item";
case MAP_LIST: return "map_list";
case TYPE_LIST: return "type_list";
case ANNOTATION_SET_REF_LIST: return "annotation_set_ref_list";

View File

@ -0,0 +1,39 @@
/*
* Copyright 2018, 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.raw;
public class MethodHandleItem {
public static final int ITEM_SIZE = 8;
public static final int METHOD_HANDLE_TYPE_OFFSET = 0;
public static final int MEMBER_ID_OFFSET = 4;
}

View File

@ -0,0 +1,160 @@
/*
* Copyright 2018, 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.reference;
import com.google.common.collect.Lists;
import org.jf.dexlib2.ValueType;
import org.jf.dexlib2.base.reference.BaseCallSiteReference;
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
import org.jf.dexlib2.dexbacked.util.EncodedArrayItemIterator;
import org.jf.dexlib2.iface.reference.MethodHandleReference;
import org.jf.dexlib2.iface.reference.MethodProtoReference;
import org.jf.dexlib2.iface.value.EncodedValue;
import org.jf.dexlib2.iface.value.MethodHandleEncodedValue;
import org.jf.dexlib2.iface.value.MethodTypeEncodedValue;
import org.jf.dexlib2.iface.value.StringEncodedValue;
import org.jf.util.ExceptionWithContext;
import javax.annotation.Nonnull;
import java.util.List;
public class DexBackedCallSiteReference extends BaseCallSiteReference {
@Nonnull public final DexBackedDexFile dexFile;
public final int callSiteIndex;
public final int callSiteIdOffset;
private int callSiteOffset = -1;
public DexBackedCallSiteReference(DexBackedDexFile dexFile, int callSiteIndex) {
this.dexFile = dexFile;
this.callSiteIndex = callSiteIndex;
this.callSiteIdOffset = dexFile.getCallSiteIdItemOffset(callSiteIndex);
}
@Nonnull
@Override
public String getName() {
return String.format("call_site_%d", callSiteIndex);
}
@Nonnull
@Override
public MethodHandleReference getMethodHandle() {
EncodedArrayItemIterator iter = getCallSiteIterator();
if (iter.getItemCount() < 3) {
throw new ExceptionWithContext("Invalid call site item: must contain at least 3 entries.");
}
EncodedValue encodedValue = getCallSiteIterator().getNextOrNull();
assert encodedValue != null;
if (encodedValue.getValueType() != ValueType.METHOD_HANDLE) {
throw new ExceptionWithContext(
"Invalid encoded value type (%d) for the first item in call site %d",
encodedValue.getValueType(), callSiteIndex);
}
return ((MethodHandleEncodedValue) encodedValue).getValue();
}
@Nonnull
@Override
public String getMethodName() {
EncodedArrayItemIterator iter = getCallSiteIterator();
if (iter.getItemCount() < 3) {
throw new ExceptionWithContext("Invalid call site item: must contain at least 3 entries.");
}
iter.skipNext();
EncodedValue encodedValue = iter.getNextOrNull();
assert encodedValue != null;
if (encodedValue.getValueType() != ValueType.STRING) {
throw new ExceptionWithContext(
"Invalid encoded value type (%d) for the second item in call site %d",
encodedValue.getValueType(), callSiteIndex);
}
return ((StringEncodedValue) encodedValue).getValue();
}
@Nonnull
@Override
public MethodProtoReference getMethodProto() {
EncodedArrayItemIterator iter = getCallSiteIterator();
if (iter.getItemCount() < 3) {
throw new ExceptionWithContext("Invalid call site item: must contain at least 3 entries.");
}
iter.skipNext();
iter.skipNext();
EncodedValue encodedValue = iter.getNextOrNull();
assert encodedValue != null;
if (encodedValue.getValueType() != ValueType.METHOD_TYPE) {
throw new ExceptionWithContext(
"Invalid encoded value type (%d) for the second item in call site %d",
encodedValue.getValueType(), callSiteIndex);
}
return ((MethodTypeEncodedValue) encodedValue).getValue();
}
@Nonnull
@Override
public List<? extends EncodedValue> getExtraArguments() {
List<EncodedValue> values = Lists.newArrayList();
EncodedArrayItemIterator iter = getCallSiteIterator();
if (iter.getItemCount() < 3) {
throw new ExceptionWithContext("Invalid call site item: must contain at least 3 entries.");
}
if (iter.getItemCount() == 3) {
return values;
}
iter.skipNext();
iter.skipNext();
iter.skipNext();
EncodedValue item = iter.getNextOrNull();
while (item != null) {
values.add(item);
item = iter.getNextOrNull();
}
return values;
}
private EncodedArrayItemIterator getCallSiteIterator() {
return EncodedArrayItemIterator.newOrEmpty(dexFile, getCallSiteOffset());
}
private int getCallSiteOffset() {
if (callSiteOffset < 0) {
callSiteOffset = dexFile.readSmallUint(callSiteIdOffset);
}
return callSiteOffset;
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright 2018, 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.reference;
import org.jf.dexlib2.MethodHandleType;
import org.jf.dexlib2.base.reference.BaseMethodHandleReference;
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
import org.jf.dexlib2.dexbacked.raw.MethodHandleItem;
import org.jf.dexlib2.iface.reference.Reference;
import org.jf.util.ExceptionWithContext;
import javax.annotation.Nonnull;
public class DexBackedMethodHandleReference extends BaseMethodHandleReference {
@Nonnull public final DexBackedDexFile dexFile;
public final int methodHandleIndex;
public final int methodHandleOffset;
public DexBackedMethodHandleReference(DexBackedDexFile dexFile, int methodHandleIndex) {
this.dexFile = dexFile;
this.methodHandleIndex = methodHandleIndex;
this.methodHandleOffset = dexFile.getMethodHandleItemOffset(methodHandleIndex);
}
@Override
public int getMethodHandleType() {
return dexFile.readUshort(methodHandleOffset + MethodHandleItem.METHOD_HANDLE_TYPE_OFFSET);
}
@Nonnull
@Override
public Reference getMemberReference() {
int memberIndex = dexFile.readUshort(methodHandleOffset + MethodHandleItem.MEMBER_ID_OFFSET);
switch (getMethodHandleType()) {
case MethodHandleType.INSTANCE_GET:
case MethodHandleType.INSTANCE_PUT:
case MethodHandleType.STATIC_GET:
case MethodHandleType.STATIC_PUT:
return new DexBackedFieldReference(dexFile, memberIndex);
case MethodHandleType.INVOKE_INSTANCE:
case MethodHandleType.INVOKE_STATIC:
return new DexBackedMethodReference(dexFile, memberIndex);
default:
throw new ExceptionWithContext("Invalid method handle type: %d", getMethodHandleType());
}
}
}

View File

@ -101,6 +101,12 @@ public abstract class DexBackedEncodedValue {
case ValueType.BOOLEAN:
Preconditions.checkValueArg(valueArg, 1);
return ImmutableBooleanEncodedValue.forBoolean(valueArg == 1);
case ValueType.METHOD_HANDLE:
Preconditions.checkValueArg(valueArg, 3);
return new DexBackedMethodHandleEncodedValue(reader, valueArg);
case ValueType.METHOD_TYPE:
Preconditions.checkValueArg(valueArg, 3);
return new DexBackedMethodTypeEncodedValue(reader, valueArg);
default:
throw new ExceptionWithContext("Invalid encoded_value type: 0x%x", valueType);
}
@ -131,6 +137,8 @@ public abstract class DexBackedEncodedValue {
case ValueType.FIELD:
case ValueType.METHOD:
case ValueType.ENUM:
case ValueType.METHOD_HANDLE:
case ValueType.METHOD_TYPE:
int valueArg = b >>> 5;
reader.moveRelative(valueArg+1);
break;

View File

@ -0,0 +1,56 @@
/*
* Copyright 2018, 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.value;
import org.jf.dexlib2.base.value.BaseMethodHandleEncodedValue;
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
import org.jf.dexlib2.dexbacked.DexReader;
import org.jf.dexlib2.dexbacked.reference.DexBackedMethodHandleReference;
import org.jf.dexlib2.iface.reference.MethodHandleReference;
import javax.annotation.Nonnull;
public class DexBackedMethodHandleEncodedValue extends BaseMethodHandleEncodedValue {
@Nonnull public final DexBackedDexFile dexFile;
private final int methodHandleIndex;
public DexBackedMethodHandleEncodedValue(@Nonnull DexReader reader, int valueArg) {
this.dexFile = reader.dexBuf;
this.methodHandleIndex = reader.readSizedSmallUint(valueArg + 1);
}
@Nonnull
@Override
public MethodHandleReference getValue() {
return new DexBackedMethodHandleReference(dexFile, methodHandleIndex);
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright 2018, 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.value;
import org.jf.dexlib2.base.value.BaseMethodTypeEncodedValue;
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
import org.jf.dexlib2.dexbacked.DexReader;
import org.jf.dexlib2.dexbacked.reference.DexBackedMethodProtoReference;
import org.jf.dexlib2.iface.reference.MethodProtoReference;
import javax.annotation.Nonnull;
public class DexBackedMethodTypeEncodedValue extends BaseMethodTypeEncodedValue {
@Nonnull public final DexBackedDexFile dexFile;
private final int methodProtoIndex;
public DexBackedMethodTypeEncodedValue(@Nonnull DexReader reader, int valueArg) {
this.dexFile = reader.dexBuf;
this.methodProtoIndex = reader.readSizedSmallUint(valueArg + 1);
}
@Nonnull
@Override
public MethodProtoReference getValue() {
return new DexBackedMethodProtoReference(dexFile, methodProtoIndex);
}
}