Mercurial > hg > icedrobot > daneel
changeset 14:e5a9ae57cbf8
Adapted class data parser to recent changes.
* dex/ClassData.java: Resolves method ids, parses code and static field values.
(accept, acceptField, acceptMethod): Implemented visitor pattern.
* dex/ClassDef.java: Pass static values offset to class data parser.
author | Michael Starzinger <michi@complang.tuwien.ac.at> |
---|---|
date | Tue, 15 Mar 2011 00:43:32 +0100 |
parents | cb4a1dc20293 |
children | e825bcb0ee95 |
files | src/main/java/org/icedrobot/daneel/dex/ClassData.java src/main/java/org/icedrobot/daneel/dex/ClassDef.java |
diffstat | 2 files changed, 104 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/src/main/java/org/icedrobot/daneel/dex/ClassData.java Tue Mar 15 00:11:00 2011 +0100 +++ b/src/main/java/org/icedrobot/daneel/dex/ClassData.java Tue Mar 15 00:43:32 2011 +0100 @@ -29,10 +29,13 @@ * current position. * @param buffer The byte buffer to read from. * @param dex The DEX file currently being parsed. + * @param staticValuesOff Offset to the list of initial values for static + * fields as stored in {@code class_def_item}, or 0 in case there are none. * @return An object representing the parsed data. */ - static ClassData parse(ByteBuffer buffer, DexFile dex) { - return new ClassData(buffer, dex); + public static ClassData parse(ByteBuffer buffer, DexFile dex, + int staticValuesOff) { + return new ClassData(buffer, dex, staticValuesOff); } private int staticFieldsSize; @@ -49,15 +52,17 @@ private FieldId[] instanceFieldsIds; private int[] instanceFieldsFlags; - private int[] directMethodsIdxDiff; + private final MethodId[] directMethodsIds; private int[] directMethodsFlags; - private int[] directMethodsCodeOff; + private final Code[] directMethodsCode; - private int[] virtualMethodsIdxDiff; + private final MethodId[] virtualMethodsIds; private int[] virtualMethodsFlags; - private int[] virtualMethodsCodeOff; + private final Code[] virtualMethodsCode; - private ClassData(ByteBuffer buffer, DexFile dex) { + private final Object[] staticValues; + + private ClassData(ByteBuffer buffer, DexFile dex, int staticValuesOff) { staticFieldsSize = BufferUtil.getULEB128(buffer); instanceFieldsSize = BufferUtil.getULEB128(buffer); directMethodsSize = BufferUtil.getULEB128(buffer); @@ -86,24 +91,42 @@ } // Parse encoded_method structures in direct_methods array. - directMethodsIdxDiff = new int[directMethodsSize]; + directMethodsIds = new MethodId[directMethodsSize]; directMethodsFlags = new int[directMethodsSize]; - directMethodsCodeOff = new int[directMethodsSize]; + directMethodsCode = new Code[directMethodsSize]; + int directMethodsIdx = 0; for (int i = 0; i < directMethodsSize; i++) { - directMethodsIdxDiff[i] = BufferUtil.getULEB128(buffer); + directMethodsIdx += BufferUtil.getULEB128(buffer); + directMethodsIds[i] = dex.getMethodId(directMethodsIdx); directMethodsFlags[i] = BufferUtil.getULEB128(buffer); - directMethodsCodeOff[i] = BufferUtil.getULEB128(buffer); + int codeOff = BufferUtil.getULEB128(buffer); + if (codeOff != 0) + directMethodsCode[i] = Code.parse(dex.getDataBuffer(codeOff), dex); } // Parse encoded_method structures in virtual_methods array. - virtualMethodsIdxDiff = new int[virtualMethodsSize]; + virtualMethodsIds = new MethodId[virtualMethodsSize]; virtualMethodsFlags = new int[virtualMethodsSize]; - virtualMethodsCodeOff = new int[virtualMethodsSize]; + virtualMethodsCode = new Code[virtualMethodsSize]; + int virtualMethodsIdx = 0; for (int i = 0; i < virtualMethodsSize; i++) { - virtualMethodsIdxDiff[i] = BufferUtil.getULEB128(buffer); + virtualMethodsIdx += BufferUtil.getULEB128(buffer); + virtualMethodsIds[i] = dex.getMethodId(virtualMethodsIdx); virtualMethodsFlags[i] = BufferUtil.getULEB128(buffer); - virtualMethodsCodeOff[i] = BufferUtil.getULEB128(buffer); + int codeOff = BufferUtil.getULEB128(buffer); + if (codeOff != 0) + virtualMethodsCode[i] = Code.parse(dex.getDataBuffer(codeOff), dex); } + + // Parse encoded_array_item and contained encoded_value structures. + if (staticValuesOff != 0) { + ByteBuffer buf = dex.getDataBuffer(staticValuesOff); + int staticValuesSize = BufferUtil.getULEB128(buf); + staticValues = new Object[staticValuesSize]; + for (int i = 0; i < staticValuesSize; i++) + staticValues[i] = EncodedValue.parse(buf, dex); + } else + staticValues = new Object[0]; } public int getStaticFieldsSize() { @@ -145,4 +168,69 @@ public int getVirtualMethodsFlag(int idx) { return virtualMethodsFlags[idx]; } + + /** + * Allows the given visitor to visit this class data object. + * @param visitor The given DEX class visitor object. + */ + public void accept(DexClassVisitor visitor) { + + // Visit all static fields. + for (int i = 0; i < staticFieldsSize; i++) { + int access = staticFieldsFlags[i]; + FieldId field = staticFieldsIds[i]; + Object value = (i < staticValues.length) ? staticValues[i] : null; + acceptField(visitor, access, field, value); + } + + // Visit all instance fields. + for (int i = 0; i < instanceFieldsSize; i++) { + int access = instanceFieldsFlags[i]; + FieldId field = instanceFieldsIds[i]; + acceptField(visitor, access, field, null); + } + + // Visit all direct methods. + for (int i = 0; i < directMethodsSize; i++) { + int access = directMethodsFlags[i]; + MethodId method = directMethodsIds[i]; + Code code = directMethodsCode[i]; + acceptMethod(visitor, access, method, code); + } + + // Visit all virtual methods. + for (int i = 0; i < virtualMethodsSize; i++) { + int access = virtualMethodsFlags[i]; + MethodId method = virtualMethodsIds[i]; + Code code = virtualMethodsCode[i]; + acceptMethod(visitor, access, method, code); + } + } + + /** + * Helper method to visit a field. + */ + private static void acceptField(DexClassVisitor visitor, int access, + FieldId field, Object value) { + DexFieldVisitor dfv = visitor.visitField(access, field.getName(), + field.getTypeDescriptor(), value); + if (dfv != null) + dfv.visitEnd(); + } + + /** + * Helper method to visit a method. + */ + private static void acceptMethod(DexClassVisitor visitor, int access, + MethodId method, Code code) { + ProtoId proto = method.getProtoId(); + DexMethodVisitor dmv = visitor.visitMethod(access, + method.getName(), proto.getShorty(), proto.getReturnType(), + proto.getParameters()); + if (dmv == null) + return; + if (code != null) + code.accept(dmv); + dmv.visitEnd(); + } }
--- a/src/main/java/org/icedrobot/daneel/dex/ClassDef.java Tue Mar 15 00:11:00 2011 +0100 +++ b/src/main/java/org/icedrobot/daneel/dex/ClassDef.java Tue Mar 15 00:43:32 2011 +0100 @@ -73,7 +73,7 @@ // Parse the associated class_data_item structure. buf.position(classDataOff); - classData = ClassData.parse(buf, dex); + classData = ClassData.parse(buf, dex, staticValuesOff); } public String getClassName() {