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