1c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver/* 2c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * Copyright 2012, Google Inc. 3c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * All rights reserved. 4c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * 5c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * Redistribution and use in source and binary forms, with or without 6c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * modification, are permitted provided that the following conditions are 7c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * met: 8c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * 9c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * * Redistributions of source code must retain the above copyright 10c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * notice, this list of conditions and the following disclaimer. 11c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * * Redistributions in binary form must reproduce the above 12c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * copyright notice, this list of conditions and the following disclaimer 13c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * in the documentation and/or other materials provided with the 14c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * distribution. 15c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * * Neither the name of Google Inc. nor the names of its 16c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * contributors may be used to endorse or promote products derived from 17c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * this software without specific prior written permission. 18c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * 19c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver */ 31c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver 32c307c1887d0c57e2213d5146cedec2307251e9faBen Gruverpackage org.jf.dexlib2.dexbacked.instruction; 33c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver 34c307c1887d0c57e2213d5146cedec2307251e9faBen Gruverimport org.jf.dexlib2.Opcode; 3584c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruverimport org.jf.dexlib2.dexbacked.DexBackedDexFile; 36c307c1887d0c57e2213d5146cedec2307251e9faBen Gruverimport org.jf.dexlib2.dexbacked.util.FixedSizeList; 37c307c1887d0c57e2213d5146cedec2307251e9faBen Gruverimport org.jf.dexlib2.iface.instruction.formats.ArrayPayload; 38c307c1887d0c57e2213d5146cedec2307251e9faBen Gruverimport org.jf.util.ExceptionWithContext; 39c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver 40c307c1887d0c57e2213d5146cedec2307251e9faBen Gruverimport javax.annotation.Nonnull; 41c307c1887d0c57e2213d5146cedec2307251e9faBen Gruverimport java.util.List; 42c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver 43b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruverpublic class DexBackedArrayPayload extends DexBackedInstruction implements ArrayPayload { 44c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver public static final Opcode OPCODE = Opcode.ARRAY_PAYLOAD; 45c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver 46c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver public final int elementWidth; 47c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver public final int elementCount; 48c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver 49c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver private static final int ELEMENT_WIDTH_OFFSET = 2; 50c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver private static final int ELEMENT_COUNT_OFFSET = 4; 51c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver private static final int ELEMENTS_OFFSET = 8; 52c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver 5384c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver public DexBackedArrayPayload(@Nonnull DexBackedDexFile dexFile, 54b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver int instructionStart) { 5584c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver super(dexFile, OPCODE, instructionStart); 56c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver 5784c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver elementWidth = dexFile.readUshort(instructionStart + ELEMENT_WIDTH_OFFSET); 5884c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver elementCount = dexFile.readSmallUint(instructionStart + ELEMENT_COUNT_OFFSET); 59c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver } 60c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver 61c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver @Override public int getElementWidth() { return elementWidth; } 62c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver 63c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver @Nonnull 64c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver @Override 65c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver public List<Number> getArrayElements() { 66b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1Ben Gruver final int elementsStart = instructionStart + ELEMENTS_OFFSET; 67c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver 68c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver abstract class ReturnedList extends FixedSizeList<Number> { 69c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver @Override public int size() { return elementCount; } 70c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver } 71c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver 72c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver switch (elementWidth) { 73c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver case 1: 74c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver return new ReturnedList() { 75c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver @Nonnull 76c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver @Override 77c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver public Number readItem(int index) { 7884c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver return dexFile.readByte(elementsStart + index); 79c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver } 80c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver }; 81c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver case 2: 82c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver return new ReturnedList() { 83c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver @Nonnull 84c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver @Override 85c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver public Number readItem(int index) { 8684c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver return dexFile.readShort(elementsStart + index*2); 87c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver } 88c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver }; 89c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver case 4: 90c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver return new ReturnedList() { 91c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver @Nonnull 92c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver @Override 93c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver public Number readItem(int index) { 9484c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver return dexFile.readInt(elementsStart + index*4); 95c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver } 96c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver }; 97c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver case 8: 98c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver return new ReturnedList() { 99c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver @Nonnull 100c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver @Override 101c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver public Number readItem(int index) { 10284c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver return dexFile.readLong(elementsStart + index*8); 103c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver } 104c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver }; 105c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver default: 106c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver throw new ExceptionWithContext("Invalid element width: %d", elementWidth); 107c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver } 108c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver } 109c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver 110c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver @Override 111c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver public int getCodeUnits() { 112c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver return 4 + (elementWidth*elementCount + 1) / 2; 113c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver } 114c307c1887d0c57e2213d5146cedec2307251e9faBen Gruver} 115