Remove the DebugItem template parameter from ClassSection

In DexBuilder, instead of statically specifying a specific DebugItem type,
we dynamically check that the various String/Type References returned by
the items are of the proper type
This commit is contained in:
Ben Gruver 2013-08-24 21:21:27 -07:00
parent a4e0efe9a5
commit 9bbcaae91f
12 changed files with 105 additions and 231 deletions

View File

@ -31,8 +31,11 @@
package org.jf.dexlib2.iface.debug;
import org.jf.dexlib2.iface.reference.StringReference;
import javax.annotation.Nullable;
public interface SetSourceFile extends DebugItem {
@Nullable String getSourceFile();
@Nullable StringReference getSourceFileReference();
}

View File

@ -31,6 +31,15 @@
package org.jf.dexlib2.iface.debug;
import org.jf.dexlib2.iface.reference.StringReference;
import org.jf.dexlib2.iface.reference.TypeReference;
import javax.annotation.Nullable;
public interface StartLocal extends DebugItem, LocalInfo {
int getRegister();
@Nullable StringReference getNameReference();
@Nullable TypeReference getTypeReference();
@Nullable StringReference getSignatureReference();
}

View File

@ -32,7 +32,9 @@
package org.jf.dexlib2.immutable.debug;
import org.jf.dexlib2.DebugItemType;
import org.jf.dexlib2.base.reference.BaseStringReference;
import org.jf.dexlib2.iface.debug.SetSourceFile;
import org.jf.dexlib2.iface.reference.StringReference;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -58,5 +60,14 @@ public class ImmutableSetSourceFile extends ImmutableDebugItem implements SetSou
@Nullable @Override public String getSourceFile() { return sourceFile; }
@Nullable @Override public StringReference getSourceFileReference() {
return sourceFile==null?null:new BaseStringReference() {
@Nonnull @Override public String getString() {
return sourceFile;
}
};
}
@Override public int getDebugItemType() { return DebugItemType.SET_SOURCE_FILE; }
}

View File

@ -32,7 +32,11 @@
package org.jf.dexlib2.immutable.debug;
import org.jf.dexlib2.DebugItemType;
import org.jf.dexlib2.base.reference.BaseStringReference;
import org.jf.dexlib2.base.reference.BaseTypeReference;
import org.jf.dexlib2.iface.debug.StartLocal;
import org.jf.dexlib2.iface.reference.StringReference;
import org.jf.dexlib2.iface.reference.TypeReference;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -69,6 +73,31 @@ public class ImmutableStartLocal extends ImmutableDebugItem implements StartLoca
}
@Override public int getRegister() { return register; }
@Nullable @Override public StringReference getNameReference() {
return name==null?null:new BaseStringReference() {
@Nonnull @Override public String getString() {
return name;
}
};
}
@Nullable @Override public TypeReference getTypeReference() {
return type==null?null:new BaseTypeReference() {
@Nonnull @Override public String getType() {
return type;
}
};
}
@Nullable @Override public StringReference getSignatureReference() {
return signature==null?null:new BaseStringReference() {
@Nonnull @Override public String getString() {
return signature;
}
};
}
@Nullable @Override public String getName() { return name; }
@Nullable @Override public String getType() { return type; }
@Nullable @Override public String getSignature() { return signature; }

View File

@ -32,6 +32,7 @@
package org.jf.dexlib2.writer;
import org.jf.dexlib2.iface.TryBlock;
import org.jf.dexlib2.iface.debug.DebugItem;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -41,7 +42,7 @@ import java.util.List;
import java.util.Map;
public interface ClassSection<StringKey extends CharSequence, TypeKey extends CharSequence, TypeListKey, ClassKey,
FieldKey, MethodKey, AnnotationSetKey, EncodedValue, DebugItem, Insn,
FieldKey, MethodKey, AnnotationSetKey, EncodedValue, Insn,
ExceptionHandler extends org.jf.dexlib2.iface.ExceptionHandler> extends IndexSection<ClassKey> {
@Nonnull Collection<? extends ClassKey> getSortedClasses();

View File

@ -40,6 +40,7 @@ import org.jf.dexlib2.base.BaseAnnotation;
import org.jf.dexlib2.dexbacked.raw.*;
import org.jf.dexlib2.iface.Annotation;
import org.jf.dexlib2.iface.TryBlock;
import org.jf.dexlib2.iface.debug.DebugItem;
import org.jf.dexlib2.iface.debug.LineNumber;
import org.jf.dexlib2.iface.instruction.Instruction;
import org.jf.dexlib2.iface.instruction.formats.*;
@ -75,7 +76,6 @@ public abstract class DexWriter<
TypeListKey,
FieldKey, MethodKey,
EncodedValue, AnnotationElement,
DebugItem extends org.jf.dexlib2.iface.debug.DebugItem,
Insn extends Instruction, ExceptionHandler extends org.jf.dexlib2.iface.ExceptionHandler> {
public static final int NO_INDEX = -1;
public static final int NO_OFFSET = 0;
@ -116,7 +116,7 @@ public abstract class DexWriter<
protected final FieldSection<StringKey, TypeKey, FieldRefKey, FieldKey> fieldSection;
protected final MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey, MethodKey> methodSection;
protected final ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey,
EncodedValue, DebugItem, Insn, ExceptionHandler> classSection;
EncodedValue, Insn, ExceptionHandler> classSection;
protected final TypeListSection<TypeKey, TypeListKey> typeListSection;
protected final AnnotationSection<StringKey, TypeKey, AnnotationKey, AnnotationElement, EncodedValue> annotationSection;
@ -130,7 +130,7 @@ public abstract class DexWriter<
FieldSection<StringKey, TypeKey, FieldRefKey, FieldKey> fieldSection,
MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey, MethodKey> methodSection,
ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey,
EncodedValue, DebugItem, Insn, ExceptionHandler> classSection,
EncodedValue, Insn, ExceptionHandler> classSection,
TypeListSection<TypeKey, TypeListKey> typeListSection,
AnnotationSection<StringKey, TypeKey, AnnotationKey, AnnotationElement,
EncodedValue> annotationSection,

View File

@ -37,15 +37,13 @@ import com.google.common.collect.*;
import org.jf.dexlib2.DebugItemType;
import org.jf.dexlib2.iface.Field;
import org.jf.dexlib2.iface.TryBlock;
import org.jf.dexlib2.iface.debug.EndLocal;
import org.jf.dexlib2.iface.debug.LineNumber;
import org.jf.dexlib2.iface.debug.RestartLocal;
import org.jf.dexlib2.iface.debug.*;
import org.jf.dexlib2.iface.reference.StringReference;
import org.jf.dexlib2.iface.reference.TypeReference;
import org.jf.dexlib2.iface.value.EncodedValue;
import org.jf.dexlib2.util.EncodedValueUtils;
import org.jf.dexlib2.writer.ClassSection;
import org.jf.dexlib2.writer.DebugWriter;
import org.jf.dexlib2.writer.builder.BuilderDebugItem.BuilderSetSourceFile;
import org.jf.dexlib2.writer.builder.BuilderDebugItem.BuilderStartLocal;
import org.jf.dexlib2.writer.builder.BuilderEncodedValues.BuilderEncodedValue;
import org.jf.util.AbstractForwardSequentialList;
import org.jf.util.CollectionUtils;
@ -59,8 +57,8 @@ import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
public class BuilderClassPool implements ClassSection<BuilderStringReference, BuilderTypeReference, BuilderTypeList,
BuilderClassDef, BuilderField, BuilderMethod, BuilderAnnotationSet, BuilderEncodedValue, BuilderDebugItem,
BuilderInstruction, BuilderExceptionHandler> {
BuilderClassDef, BuilderField, BuilderMethod, BuilderAnnotationSet, BuilderEncodedValue, BuilderInstruction,
BuilderExceptionHandler> {
@Nonnull private final ConcurrentMap<String, BuilderClassDef> internedItems =
Maps.newConcurrentMap();
@ -266,7 +264,7 @@ public class BuilderClassPool implements ClassSection<BuilderStringReference, Bu
}
@Nullable @Override
public Iterable<? extends BuilderDebugItem> getDebugItems(@Nonnull BuilderMethod builderMethod) {
public Iterable<? extends DebugItem> getDebugItems(@Nonnull BuilderMethod builderMethod) {
BuilderMethodImplementation impl = builderMethod.getImplementation();
if (impl == null) {
return null;
@ -353,17 +351,41 @@ public class BuilderClassPool implements ClassSection<BuilderStringReference, Bu
return builderMethod.debugInfoOffset;
}
@Nullable private BuilderStringReference checkStringReference(@Nullable StringReference stringReference) {
if (stringReference == null) {
return null;
}
try {
return (BuilderStringReference)stringReference;
} catch (ClassCastException ex) {
throw new IllegalStateException("Only StringReference instances returned by " +
"DexBuilder.internStringReference or DexBuilder.internNullableStringReference may be used.");
}
}
@Nullable private BuilderTypeReference checkTypeReference(@Nullable TypeReference typeReference) {
if (typeReference == null) {
return null;
}
try {
return (BuilderTypeReference)typeReference;
} catch (ClassCastException ex) {
throw new IllegalStateException("Only TypeReference instances returned by " +
"DexBuilder.internTypeReference or DexBuilder.internNullableTypeReference may be used.");
}
}
@Override
public void writeDebugItem(@Nonnull DebugWriter<BuilderStringReference, BuilderTypeReference> writer,
BuilderDebugItem debugItem) throws IOException {
DebugItem debugItem) throws IOException {
switch (debugItem.getDebugItemType()) {
case DebugItemType.START_LOCAL: {
BuilderStartLocal startLocal = (BuilderStartLocal)debugItem;
StartLocal startLocal = (StartLocal)debugItem;
writer.writeStartLocal(startLocal.getCodeAddress(),
startLocal.register,
startLocal.name,
startLocal.type,
startLocal.signature);
startLocal.getRegister(),
checkStringReference(startLocal.getNameReference()),
checkTypeReference(startLocal.getTypeReference()),
checkStringReference(startLocal.getSignatureReference()));
break;
}
case DebugItemType.END_LOCAL: {
@ -390,8 +412,9 @@ public class BuilderClassPool implements ClassSection<BuilderStringReference, Bu
break;
}
case DebugItemType.SET_SOURCE_FILE: {
BuilderSetSourceFile setSourceFile = (BuilderSetSourceFile)debugItem;
writer.writeSetSourceFile(setSourceFile.getCodeAddress(), setSourceFile.sourceFile);
SetSourceFile setSourceFile = (SetSourceFile)debugItem;
writer.writeSetSourceFile(setSourceFile.getCodeAddress(),
checkStringReference(setSourceFile.getSourceFileReference()));
}
default:
throw new ExceptionWithContext("Unexpected debug item type: %d", debugItem.getDebugItemType());

View File

@ -1,168 +0,0 @@
/*
* Copyright 2013, 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.writer.builder;
import org.jf.dexlib2.DebugItemType;
import org.jf.dexlib2.iface.debug.*;
import org.jf.dexlib2.immutable.debug.ImmutableEpilogueBegin;
import org.jf.dexlib2.immutable.debug.ImmutableLineNumber;
import org.jf.dexlib2.immutable.debug.ImmutablePrologueEnd;
import javax.annotation.Nullable;
public abstract interface BuilderDebugItem extends DebugItem {
abstract static class BaseBuilderDebugItem implements BuilderDebugItem {
final int codeAddress;
public BaseBuilderDebugItem(int codeAddress) {
this.codeAddress = codeAddress;
}
@Override public int getCodeAddress() { return codeAddress; }
}
public static class BuilderStartLocal extends BaseBuilderDebugItem implements StartLocal {
final int register;
@Nullable final BuilderStringReference name;
@Nullable final BuilderTypeReference type;
@Nullable final BuilderStringReference signature;
BuilderStartLocal(int codeAddress,
int register,
@Nullable BuilderStringReference name,
@Nullable BuilderTypeReference type,
@Nullable BuilderStringReference signature) {
super(codeAddress);
this.register = register;
this.name = name;
this.type = type;
this.signature = signature;
}
@Override public int getRegister() { return register; }
@Nullable @Override public String getName() { return name==null?null:name.getString(); }
@Nullable @Override public String getType() { return type==null?null:type.getType(); }
@Nullable @Override public String getSignature() { return signature==null?null:signature.getString(); }
@Override public int getDebugItemType() { return DebugItemType.START_LOCAL; }
}
public static class BuilderEndLocal extends BaseBuilderDebugItem implements EndLocal {
private final int register;
BuilderEndLocal(int codeAddress, int register) {
super(codeAddress);
this.register = register;
}
@Override public int getRegister() {
return register;
}
@Override public int getDebugItemType() {
return DebugItemType.END_LOCAL;
}
@Nullable @Override public String getName() {
return null;
}
@Nullable @Override public String getType() {
return null;
}
@Nullable @Override public String getSignature() {
return null;
}
}
public static class BuilderRestartLocal extends BaseBuilderDebugItem implements RestartLocal {
private final int register;
BuilderRestartLocal(int codeAddress, int register) {
super(codeAddress);
this.register = register;
}
@Override public int getRegister() {
return register;
}
@Override public int getDebugItemType() {
return DebugItemType.RESTART_LOCAL;
}
@Nullable @Override public String getName() {
return null;
}
@Nullable @Override public String getType() {
return null;
}
@Nullable @Override public String getSignature() {
return null;
}
}
public static class BuilderPrologueEnd extends ImmutablePrologueEnd implements BuilderDebugItem {
BuilderPrologueEnd(int codeAddress) {
super(codeAddress);
}
}
public static class BuilderEpilogueBegin extends ImmutableEpilogueBegin implements BuilderDebugItem {
BuilderEpilogueBegin(int codeAddress) {
super(codeAddress);
}
}
public static class BuilderLineNumber extends ImmutableLineNumber implements BuilderDebugItem {
BuilderLineNumber(int codeAddress, int lineNumber) {
super(codeAddress, lineNumber);
}
}
public static class BuilderSetSourceFile extends BaseBuilderDebugItem implements SetSourceFile {
@Nullable final BuilderStringReference sourceFile;
BuilderSetSourceFile(int codeAddress,
@Nullable BuilderStringReference sourceFile) {
super(codeAddress);
this.sourceFile = sourceFile;
}
@Nullable @Override public String getSourceFile() { return sourceFile==null?null:sourceFile.getString(); }
@Override public int getDebugItemType() { return DebugItemType.SET_SOURCE_FILE; }
}
}

View File

@ -32,6 +32,7 @@
package org.jf.dexlib2.writer.builder;
import org.jf.dexlib2.iface.MethodImplementation;
import org.jf.dexlib2.iface.debug.DebugItem;
import javax.annotation.Nonnull;
import java.util.List;
@ -40,12 +41,12 @@ public class BuilderMethodImplementation implements MethodImplementation {
protected final int registerCount;
@Nonnull protected final List<? extends BuilderInstruction> instructions;
@Nonnull protected final List<? extends BuilderTryBlock> tryBlocks;
@Nonnull protected final List<? extends BuilderDebugItem> debugItems;
@Nonnull protected final List<? extends DebugItem> debugItems;
public BuilderMethodImplementation(int registerCount,
@Nonnull List<? extends BuilderInstruction> instructions,
@Nonnull List<? extends BuilderTryBlock> tryBlocks,
@Nonnull List<? extends BuilderDebugItem> debugItems) {
@Nonnull List<? extends DebugItem> debugItems) {
this.registerCount = registerCount;
this.instructions = instructions;
this.tryBlocks = tryBlocks;
@ -55,5 +56,5 @@ public class BuilderMethodImplementation implements MethodImplementation {
@Override public int getRegisterCount() { return registerCount; }
@Nonnull @Override public List<? extends BuilderInstruction> getInstructions() { return instructions; }
@Nonnull @Override public List<? extends BuilderTryBlock> getTryBlocks() { return tryBlocks; }
@Nonnull @Override public List<? extends BuilderDebugItem> getDebugItems() { return debugItems; }
@Nonnull @Override public List<? extends DebugItem> getDebugItems() { return debugItems; }
}

View File

@ -38,10 +38,10 @@ import com.google.common.collect.Lists;
import org.jf.dexlib2.ValueType;
import org.jf.dexlib2.iface.Annotation;
import org.jf.dexlib2.iface.MethodParameter;
import org.jf.dexlib2.iface.debug.DebugItem;
import org.jf.dexlib2.iface.reference.*;
import org.jf.dexlib2.iface.value.*;
import org.jf.dexlib2.writer.DexWriter;
import org.jf.dexlib2.writer.builder.BuilderDebugItem.*;
import org.jf.dexlib2.writer.builder.BuilderEncodedValues.*;
import org.jf.util.ExceptionWithContext;
@ -56,7 +56,7 @@ import java.util.Set;
public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringReference, BuilderTypeReference,
BuilderTypeReference, BuilderProtoReference, BuilderFieldReference, BuilderMethodReference, BuilderReference,
BuilderClassDef, BuilderAnnotation, BuilderAnnotationSet, BuilderTypeList, BuilderField, BuilderMethod,
BuilderEncodedValue, BuilderAnnotationElement, BuilderDebugItem, BuilderInstruction, BuilderExceptionHandler> {
BuilderEncodedValue, BuilderAnnotationElement, BuilderInstruction, BuilderExceptionHandler> {
private final BuilderContext context;
@ -110,7 +110,7 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
int registerCount,
@Nullable List<? extends BuilderInstruction> instructions,
@Nullable List<? extends BuilderTryBlock> tryBlocks,
@Nullable List<? extends BuilderDebugItem> debugItems) {
@Nullable List<? extends DebugItem> debugItems) {
if (instructions == null) {
instructions = ImmutableList.of();
}
@ -232,40 +232,6 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
handlerCodeAddress);
}
@Nonnull public BuilderStartLocal internStartLocal(int codeAddress, int register, @Nullable String name,
@Nullable String type, @Nullable String signature) {
return new BuilderStartLocal(codeAddress,
register,
context.stringPool.internNullableString(name),
context.typePool.internNullableType(type),
context.stringPool.internNullableString(signature));
}
@Nonnull public BuilderSetSourceFile internSetSourceFile(int codeAddress, @Nullable String sourceFile) {
return new BuilderSetSourceFile(codeAddress,
context.stringPool.internNullableString(sourceFile));
}
@Nonnull public BuilderEndLocal internEndLocal(int codeAddress, int register) {
return new BuilderEndLocal(codeAddress, register);
}
@Nonnull public BuilderRestartLocal internRestartLocal(int codeAddress, int register) {
return new BuilderRestartLocal(codeAddress, register);
}
@Nonnull public BuilderPrologueEnd internPrologueEnd(int codeAddress) {
return new BuilderPrologueEnd(codeAddress);
}
@Nonnull public BuilderEpilogueBegin internEpilogueBegin(int codeAddress) {
return new BuilderEpilogueBegin(codeAddress);
}
@Nonnull public BuilderLineNumber internLineNumber(int codeAddress, int lineNumber) {
return new BuilderLineNumber(codeAddress, lineNumber);
}
@Override protected void writeEncodedValue(@Nonnull InternalEncodedValueWriter writer,
@Nonnull BuilderEncodedValue encodedValue) throws IOException {
switch (encodedValue.getValueType()) {

View File

@ -60,7 +60,7 @@ import java.util.Map.Entry;
public class ClassPool implements ClassSection<CharSequence, CharSequence,
TypeListPool.Key<? extends Collection<? extends CharSequence>>, PoolClassDef, Field, PoolMethod,
Set<? extends Annotation>,
EncodedValue, DebugItem, Instruction, ExceptionHandler> {
EncodedValue, Instruction, ExceptionHandler> {
@Nonnull private HashMap<String, PoolClassDef> internedItems = Maps.newHashMap();
@Nonnull private final StringPool stringPool;

View File

@ -33,7 +33,6 @@ package org.jf.dexlib2.writer.pool;
import org.jf.dexlib2.ValueType;
import org.jf.dexlib2.iface.*;
import org.jf.dexlib2.iface.debug.DebugItem;
import org.jf.dexlib2.iface.instruction.Instruction;
import org.jf.dexlib2.iface.reference.*;
import org.jf.dexlib2.iface.value.*;
@ -51,7 +50,7 @@ public class DexPool extends DexWriter<CharSequence, StringReference, CharSequen
FieldReference, MethodReference, Reference, PoolClassDef,
Annotation, Set<? extends Annotation>,
TypeListPool.Key<? extends Collection<? extends CharSequence>>, Field, PoolMethod,
EncodedValue, AnnotationElement, DebugItem, Instruction, ExceptionHandler> {
EncodedValue, AnnotationElement, Instruction, ExceptionHandler> {
public static DexPool makeDexPool() {
return makeDexPool(15);