1cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver/* 2cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * Copyright 2014, Google Inc. 3cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * All rights reserved. 4cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * 5cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * Redistribution and use in source and binary forms, with or without 6cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * modification, are permitted provided that the following conditions are 7cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * met: 8cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * 9cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * * Redistributions of source code must retain the above copyright 10cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * notice, this list of conditions and the following disclaimer. 11cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * * Redistributions in binary form must reproduce the above 12cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * copyright notice, this list of conditions and the following disclaimer 13cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * in the documentation and/or other materials provided with the 14cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * distribution. 15cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * * Neither the name of Google Inc. nor the names of its 16cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * contributors may be used to endorse or promote products derived from 17cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * this software without specific prior written permission. 18cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * 19cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver */ 31cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver 32cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruverpackage org.jf.smalidea.dexlib.instruction; 33cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver 340dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruverimport com.google.common.collect.Lists; 350dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruverimport org.jf.dexlib2.Opcode; 36cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruverimport org.jf.dexlib2.iface.instruction.SwitchElement; 37cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruverimport org.jf.dexlib2.iface.instruction.formats.PackedSwitchPayload; 380dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruverimport org.jf.smalidea.psi.impl.*; 390dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruverimport org.jf.smalidea.util.InstructionUtils; 40cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver 41cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruverimport javax.annotation.Nonnull; 42cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruverimport java.util.List; 43cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver 44cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruverpublic class SmalideaPackedSwitchPayload extends SmalideaInstruction implements PackedSwitchPayload { 45cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver public SmalideaPackedSwitchPayload(@Nonnull SmaliInstruction instruction) { 46cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver super(instruction); 47cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver } 48cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver 49cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver @Nonnull @Override public List<? extends SwitchElement> getSwitchElements() { 500dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver final SmaliLiteral startKey = psiInstruction.getPackedSwitchStartKey(); 510dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver assert startKey != null; 520dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver List<SmaliPackedSwitchElement> elements = psiInstruction.getPackedSwitchElements(); 530dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver 540dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver SmaliMethod smaliMethod = psiInstruction.getParentMethod(); 550dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver SmaliInstruction packedSwitchInstruction = InstructionUtils.findFirstInstructionWithTarget( 560dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver smaliMethod, Opcode.PACKED_SWITCH, psiInstruction.getOffset()); 570dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver final int baseOffset; 580dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver 590dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver if (packedSwitchInstruction == null) { 600dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver baseOffset = 0; 610dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver } else { 620dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver baseOffset = packedSwitchInstruction.getOffset(); 630dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver } 640dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver 650dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver List<SwitchElement> newElements = Lists.newArrayList(); 660dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver // TODO: check for integer wraparound (how does art/dalvik handle that?) 670dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver int initialKey = (int)startKey.getIntegralValue(); 680dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver for (int i=0; i<elements.size(); i++) { 690dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver final SmaliPackedSwitchElement element = elements.get(i); 700dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver 710dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver final int key = initialKey + i; 720dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver 730dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver newElements.add(new SwitchElement() { 740dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver @Override public int getKey() { 750dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver return key; 760dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver } 770dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver 780dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver @Override public int getOffset() { 790dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver SmaliLabelReference labelReference = element.getTarget(); 800dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver if (labelReference == null) { 810dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver return 0; 820dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver } 830dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver 840dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver SmaliLabel label = labelReference.resolve(); 850dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver if (label == null) { 860dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver return 0; 870dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver } 880dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver 8910fd792f5970274e66f1ce9956f9188ec77cfb43Ben Gruver return (label.getOffset() - baseOffset) / 2; 900dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver } 910dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver }); 920dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver } 930dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver 940dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver return newElements; 950dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver } 960dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver 970dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver @Override public int getCodeUnits() { 980a2debe4e6eb54a440ec5acbec4e42956da33c29Ben Gruver return psiInstruction.getInstructionSize()/2; 99cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver } 100cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver} 101