• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019, Google LLC
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google LLC nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 package com.android.tools.smali.dexlib2.dexbacked;
32 
33 import com.android.tools.smali.dexlib2.dexbacked.raw.CodeItem;
34 import javax.annotation.Nonnull;
35 
36 public class CDexBackedMethodImplementation extends DexBackedMethodImplementation {
37 
CDexBackedMethodImplementation( @onnull DexBackedDexFile dexFile, @Nonnull DexBackedMethod method, int codeOffset)38     public CDexBackedMethodImplementation(
39             @Nonnull DexBackedDexFile dexFile, @Nonnull DexBackedMethod method, int codeOffset) {
40         super(dexFile, method, codeOffset);
41     }
42 
getInsCount()43     public int getInsCount() {
44         int insCount = (dexFile.getDataBuffer().readUshort(codeOffset) >> CodeItem.CDEX_INS_COUNT_SHIFT) & 0xf;
45 
46         if ((getPreheaderFlags() & CodeItem.CDEX_PREHEADER_FLAG_INS_COUNT) != 0) {
47             int preheaderCount = 1;
48 
49             if ((getPreheaderFlags() & CodeItem.CDEX_PREHEADER_FLAG_INSTRUCTIONS_SIZE) != 0) {
50                 preheaderCount+=2;
51             }
52             if ((getPreheaderFlags() & CodeItem.CDEX_PREHEADER_FLAG_REGISTER_COUNT) != 0) {
53                 preheaderCount++;
54             }
55             insCount += dexFile.getDataBuffer().readUshort(codeOffset - 2 * preheaderCount);
56         }
57         return insCount;
58     }
59 
60     @Override
getRegisterCount()61     public int getRegisterCount() {
62         int registerCount = (dexFile.getDataBuffer().readUshort(codeOffset) >> CodeItem.CDEX_REGISTER_COUNT_SHIFT) & 0xf;
63 
64         registerCount += getInsCount();
65         if ((getPreheaderFlags() & CodeItem.CDEX_PREHEADER_FLAG_REGISTER_COUNT) != 0) {
66             int preheaderCount = 1;
67             if ((getPreheaderFlags() & CodeItem.CDEX_PREHEADER_FLAG_INSTRUCTIONS_SIZE) > 0) {
68                 preheaderCount += 2;
69             }
70             registerCount += dexFile.getDataBuffer().readUshort(codeOffset - 2 * preheaderCount);
71         }
72         return registerCount;
73     }
74 
75     @Override
getInstructionsSize()76     public int getInstructionsSize() {
77         int instructionsSize = dexFile.getDataBuffer().readUshort(
78                 codeOffset + CodeItem.CDEX_INSTRUCTIONS_SIZE_AND_PREHEADER_FLAGS_OFFSET) >>
79                 CodeItem.CDEX_INSTRUCTIONS_SIZE_SHIFT;
80 
81         if ((getPreheaderFlags() & CodeItem.CDEX_PREHEADER_FLAG_INSTRUCTIONS_SIZE) != 0) {
82             instructionsSize += dexFile.getDataBuffer().readUshort(codeOffset - 2);
83             instructionsSize += dexFile.getDataBuffer().readUshort(codeOffset - 4) << 16;
84         }
85         return instructionsSize;
86     }
87 
88     @Override
getInstructionsStartOffset()89     protected int getInstructionsStartOffset() {
90         return codeOffset + 4;
91     }
92 
getPreheaderFlags()93     private int getPreheaderFlags() {
94         return dexFile.getDataBuffer().readUshort(codeOffset + CodeItem.CDEX_INSTRUCTIONS_SIZE_AND_PREHEADER_FLAGS_OFFSET) &
95                 CodeItem.CDEX_PREHEADER_FLAGS_MASK;
96     }
97 
98     @Override
getTriesSize()99     protected int getTriesSize() {
100         int triesCount = (dexFile.getDataBuffer().readUshort(codeOffset) >> CodeItem.CDEX_TRIES_SIZE_SHIFT) & 0xf;
101         if ((getPreheaderFlags() & CodeItem.CDEX_PREHEADER_FLAG_TRIES_COUNT) != 0) {
102             int preheaderCount = Integer.bitCount(getPreheaderFlags());
103             if ((getPreheaderFlags() & CodeItem.CDEX_PREHEADER_FLAG_INSTRUCTIONS_SIZE) != 0) {
104                 // The instructions size preheader is 2 shorts
105                 preheaderCount++;
106             }
107             triesCount += dexFile.getDataBuffer().readUshort(codeOffset - 2 * preheaderCount);
108         }
109         return triesCount;
110     }
111 
112     @Override
getDebugOffset()113     protected int getDebugOffset() {
114         CDexBackedDexFile cdexFile = ((CDexBackedDexFile) dexFile);
115 
116         int debugTableItemOffset = (method.methodIndex / 16) * 4;
117         int bitIndex = method.methodIndex % 16;
118 
119         int debugInfoOffsetsPos = cdexFile.getDebugInfoOffsetsPos();
120         int debugTableOffset = debugInfoOffsetsPos + cdexFile.getDebugInfoOffsetsTableOffset();
121 
122         int debugOffsetsOffset = cdexFile.getDataBuffer().readSmallUint(debugTableOffset + debugTableItemOffset);
123 
124         DexReader<? extends DexBuffer> reader = cdexFile.getDataBuffer().readerAt(debugInfoOffsetsPos + debugOffsetsOffset);
125 
126         int bitMask = reader.readUbyte() << 8;
127         bitMask += reader.readUbyte();
128 
129         if ((bitMask & (1 << bitIndex)) == 0) {
130             return 0;
131         }
132 
133         int offsetCount = Integer.bitCount(bitMask & 0xFFFF >> (16-bitIndex));
134         int baseDebugOffset = cdexFile.getDebugInfoBase();
135         for (int i=0; i<offsetCount; i++) {
136             baseDebugOffset += reader.readBigUleb128();
137         }
138         baseDebugOffset += reader.readBigUleb128();
139         return baseDebugOffset;
140     }
141 }
142