DexReader.java revision 36e2ee200517b36652a6e8fe1c5aa24ce249765e
1/* 2 * Copyright 2012, Google Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32package org.jf.dexlib2.dexbacked; 33 34import org.jf.util.ExceptionWithContext; 35 36import javax.annotation.Nonnull; 37 38public class DexReader { 39 @Nonnull private final DexBuffer dexBuf; 40 private int offset; 41 42 public DexReader(@Nonnull DexBuffer dexBuf, int offset) { 43 this.dexBuf = dexBuf; 44 this.offset = offset; 45 } 46 47 @Nonnull public DexBuffer getDexBuffer() { return dexBuf; } 48 public int getOffset() { return offset; } 49 50 public String getString(int stringIndex) { return dexBuf.getString(stringIndex); } 51 public int getFieldIdItemOffset(int fieldIndex) { return dexBuf.getFieldIdItemOffset(fieldIndex); } 52 public int getMethodIdItemOffset(int methodIndex) { return dexBuf.getMethodIdItemOffset(methodIndex); } 53 public int getProtoIdItemOffset(int methodIndex) { return dexBuf.getProtoIdItemOffset(methodIndex); } 54 public String getType(int typeIndex) { return dexBuf.getType(typeIndex); } 55 public String getField(int fieldIndex) { return dexBuf.getField(fieldIndex); } 56 public String getMethod(int methodIndex) { return dexBuf.getMethod(methodIndex); } 57 public String getReference(int type, int index) { return dexBuf.getReference(type, index); } 58 59 /** {@inheritDoc} */ 60 public int readSleb128() { 61 int end = offset; 62 int currentByteValue; 63 int result; 64 byte[] buf = dexBuf.buf; 65 66 result = buf[end++] & 0xff; 67 if (result <= 0x7f) { 68 result = (result << 25) >> 25; 69 } else { 70 currentByteValue = buf[end++] & 0xff; 71 result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7); 72 if (currentByteValue <= 0x7f) { 73 result = (result << 18) >> 18; 74 } else { 75 currentByteValue = buf[end++] & 0xff; 76 result |= (currentByteValue & 0x7f) << 14; 77 if (currentByteValue <= 0x7f) { 78 result = (result << 11) >> 11; 79 } else { 80 currentByteValue = buf[end++] & 0xff; 81 result |= (currentByteValue & 0x7f) << 21; 82 if (currentByteValue <= 0x7f) { 83 result = (result << 4) >> 4; 84 } else { 85 currentByteValue = buf[end++] & 0xff; 86 if (currentByteValue > 0x7f) { 87 throw new ExceptionWithContext( 88 "Invalid sleb128 integer encountered at offset 0x%x", offset); 89 } 90 result |= currentByteValue << 28; 91 } 92 } 93 } 94 } 95 96 offset = end; 97 return result; 98 } 99 100 public int readSmallUleb128() { 101 int end = offset; 102 int currentByteValue; 103 int result; 104 byte[] buf = dexBuf.buf; 105 106 result = buf[end++] & 0xff; 107 if (result > 0x7f) { 108 currentByteValue = buf[end++] & 0xff; 109 result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7); 110 if (currentByteValue > 0x7f) { 111 currentByteValue = buf[end++] & 0xff; 112 result |= (currentByteValue & 0x7f) << 14; 113 if (currentByteValue > 0x7f) { 114 currentByteValue = buf[end++] & 0xff; 115 result |= (currentByteValue & 0x7f) << 21; 116 if (currentByteValue > 0x7f) { 117 currentByteValue = buf[end++]; 118 119 // MSB shouldn't be set on last byte 120 if (currentByteValue < 0) { 121 throw new ExceptionWithContext( 122 "Invalid uleb128 integer encountered at offset 0x%x", offset); 123 } else if ((currentByteValue & 0xf) > 0x07) { 124 // we assume most significant bit of the result will not be set, so that it can fit into 125 // a signed integer without wrapping 126 throw new ExceptionWithContext( 127 "Encountered valid uleb128 that is out of range at offset 0x%x", offset); 128 } 129 result |= currentByteValue << 28; 130 } 131 } 132 } 133 } 134 135 offset = end; 136 return result; 137 } 138 139 public void skipUleb128() { 140 int end = offset; 141 byte currentByteValue; 142 byte[] buf = dexBuf.buf; 143 144 currentByteValue = buf[end++]; 145 if (currentByteValue < 0) { // if the MSB is set 146 currentByteValue = buf[end++]; 147 if (currentByteValue < 0) { // if the MSB is set 148 currentByteValue = buf[end++]; 149 if (currentByteValue < 0) { // if the MSB is set 150 currentByteValue = buf[end++]; 151 if (currentByteValue < 0) { // if the MSB is set 152 currentByteValue = buf[end++]; 153 if (currentByteValue < 0) { 154 throw new ExceptionWithContext( 155 "Invalid uleb128 integer encountered at offset 0x%x", offset); 156 } else if ((currentByteValue & 0xf) > 0x07) { 157 // we assume most significant bit of the result will not be set, so that it can fit into 158 // a signed integer without wrapping 159 throw new ExceptionWithContext( 160 "Encountered valid uleb128 that is out of range at offset 0x%x", offset); 161 } 162 } 163 } 164 } 165 } 166 167 offset = end; 168 } 169 170 public int readSmallUint() { 171 int o = offset; 172 int result = dexBuf.readSmallUint(o); 173 offset = o + 4; 174 return result; 175 } 176 177 public int readUshort() { 178 int o = offset; 179 int result = dexBuf.readUshort(offset); 180 offset = o + 2; 181 return result; 182 } 183 184 public int readUbyte() { 185 int o = offset; 186 int result = dexBuf.readUbyte(offset); 187 offset = o + 1; 188 return result; 189 } 190 191 public long readLong() { 192 int o = offset; 193 long result = dexBuf.readLong(offset); 194 offset = o + 2; 195 return result; 196 } 197 198 public int readInt() { 199 int o = offset; 200 int result = dexBuf.readInt(offset); 201 offset = o + 4; 202 return result; 203 } 204 205 public int readShort() { 206 int o = offset; 207 int result = dexBuf.readShort(offset); 208 offset = o + 2; 209 return result; 210 } 211 212 public int readByte() { 213 int o = offset; 214 int result = dexBuf.readByte(offset); 215 offset = o + 1; 216 return result; 217 } 218 219 public void skipByte() { offset++; } 220 public void skipBytes(int i) { offset += i; } 221 222 public int readSmallUint(int offset) { return dexBuf.readSmallUint(offset); } 223 public int readUshort(int offset) { return dexBuf.readUshort(offset); } 224 public int readUbyte(int offset) { return dexBuf.readUbyte(offset); } 225 public long readLong(int offset) { return dexBuf.readLong(offset); } 226 public int readInt(int offset) { return dexBuf.readInt(offset); } 227 public int readShort(int offset) { return dexBuf.readShort(offset); } 228 public int readByte(int offset) { return dexBuf.readByte(offset); } 229 230 231 public int readSizedInt(int bytes) { 232 int o = offset; 233 byte[] buf = dexBuf.buf; 234 235 int result; 236 switch (bytes) { 237 case 4: 238 result = (buf[o] & 0xff) | 239 ((buf[o+1] & 0xff) << 8) | 240 ((buf[o+2] & 0xff) << 16) | 241 (buf[o+3] << 24); 242 break; 243 case 3: 244 result = (buf[o] & 0xff) | 245 ((buf[o+1] & 0xff) << 8) | 246 ((buf[o+2]) << 16); 247 break; 248 case 2: 249 result = (buf[o] & 0xff) | 250 ((buf[o+1]) << 8); 251 break; 252 case 1: 253 result = buf[o]; 254 break; 255 default: 256 throw new ExceptionWithContext("Invalid size %d for sized int at offset 0x%x", bytes, offset); 257 } 258 offset = o + bytes; 259 return result; 260 } 261 262 public int readSizedSmallUint(int bytes) { 263 int o = offset; 264 byte[] buf = dexBuf.buf; 265 266 int result = 0; 267 switch (bytes) { 268 case 4: 269 int b = buf[o+3]; 270 if (b < 0) { 271 throw new ExceptionWithContext( 272 "Encountered valid sized uint that is out of range at offset 0x%x", offset); 273 } 274 result = (b & 0xff) << 24; 275 // fall-through 276 case 3: 277 result |= (buf[o+2] & 0xff) << 16; 278 // fall-through 279 case 2: 280 result |= (buf[o+1] & 0xff) << 8; 281 // fall-through 282 case 1: 283 result |= (buf[o] & 0xff); 284 break; 285 default: 286 throw new ExceptionWithContext("Invalid size %d for sized uint at offset 0x%x", bytes, offset); 287 } 288 offset = o + bytes; 289 return result; 290 } 291 292 public int readSizedRightExtendedInt(int bytes) { 293 int o = offset; 294 byte[] buf = dexBuf.buf; 295 296 int result = 0; 297 switch (bytes) { 298 case 4: 299 result = (buf[o] & 0xff) | 300 ((buf[o+1] & 0xff) << 8) | 301 ((buf[o+2] & 0xff) << 16) | 302 (buf[o+3] << 24); 303 break; 304 case 3: 305 result = (buf[o] & 0xff) << 8 | 306 ((buf[o+1] & 0xff) << 16) | 307 (buf[o+2] << 24); 308 break; 309 case 2: 310 result = (buf[o] & 0xff) << 16 | 311 (buf[o+1] << 24); 312 break; 313 case 1: 314 result = buf[o] << 24; 315 break; 316 default: 317 throw new ExceptionWithContext( 318 "Invalid size %d for sized, right extended int at offset 0x%x", bytes, offset); 319 } 320 offset = o + bytes; 321 return result; 322 } 323 324 public long readSizedRightExtendedLong(int bytes) { 325 int o = offset; 326 byte[] buf = dexBuf.buf; 327 328 long result = 0; 329 switch (bytes) { 330 case 8: 331 result = (buf[o] & 0xff) | 332 ((buf[o+1] & 0xff) << 8) | 333 ((buf[o+2] & 0xff) << 16) | 334 ((buf[o+3] & 0xff) << 24) | 335 ((buf[o+4] & 0xffL) << 32) | 336 ((buf[o+5] & 0xffL) << 40) | 337 ((buf[o+6] & 0xffL) << 48) | 338 (((long)buf[o+7]) << 56); 339 break; 340 case 7: 341 result = ((buf[o] & 0xff)) << 8 | 342 ((buf[o+1] & 0xff) << 16) | 343 ((buf[o+2] & 0xff) << 24) | 344 ((buf[o+3] & 0xffL) << 32) | 345 ((buf[o+4] & 0xffL) << 40) | 346 ((buf[o+5] & 0xffL) << 48) | 347 (((long)buf[o+6]) << 56); 348 break; 349 case 6: 350 result = ((buf[o] & 0xff)) << 16 | 351 ((buf[o+1] & 0xff) << 24) | 352 ((buf[o+2] & 0xffL) << 32) | 353 ((buf[o+3] & 0xffL) << 40) | 354 ((buf[o+4] & 0xffL) << 48) | 355 (((long)buf[o+5]) << 56); 356 break; 357 case 5: 358 result = ((buf[o] & 0xff)) << 24 | 359 ((buf[o+1] & 0xffL) << 32) | 360 ((buf[o+2] & 0xffL) << 40) | 361 ((buf[o+3] & 0xffL) << 48) | 362 (((long)buf[o+4]) << 56); 363 break; 364 case 4: 365 result = ((buf[o] & 0xffL)) << 32 | 366 ((buf[o+1] & 0xffL) << 40) | 367 ((buf[o+2] & 0xffL) << 48) | 368 (((long)buf[o+3]) << 56); 369 break; 370 case 3: 371 result = ((buf[o] & 0xffL)) << 40 | 372 ((buf[o+1] & 0xffL) << 48) | 373 (((long)buf[o+2]) << 56); 374 break; 375 case 2: 376 result = ((buf[o] & 0xffL)) << 48 | 377 (((long)buf[o+1]) << 56); 378 break; 379 case 1: 380 result = ((long)buf[o]) << 56; 381 break; 382 default: 383 throw new ExceptionWithContext( 384 "Invalid size %d for sized, right extended long at offset 0x%x", bytes, offset); 385 } 386 offset = o + bytes; 387 return result; 388 } 389 390 public long readSizedLong(int bytes) { 391 int o = offset; 392 byte[] buf = dexBuf.buf; 393 394 long result = 0; 395 switch (bytes) { 396 case 8: 397 result = (buf[o] & 0xff) | 398 ((buf[o+1] & 0xff) << 8) | 399 ((buf[o+2] & 0xff) << 16) | 400 ((buf[o+3] & 0xff) << 24) | 401 ((buf[o+4] & 0xffL) << 32) | 402 ((buf[o+5] & 0xffL) << 40) | 403 ((buf[o+6] & 0xffL) << 48) | 404 (((long)buf[o+7]) << 56); 405 break; 406 case 7: 407 result = (buf[o] & 0xff) | 408 ((buf[o+1] & 0xff) << 8) | 409 ((buf[o+2] & 0xff) << 16) | 410 ((buf[o+3] & 0xff) << 24) | 411 ((buf[o+4] & 0xffL) << 32) | 412 ((buf[o+5] & 0xffL) << 40) | 413 ((long)(buf[o+6]) << 48); 414 break; 415 case 6: 416 result = (buf[o] & 0xff) | 417 ((buf[o+1] & 0xff) << 8) | 418 ((buf[o+2] & 0xff) << 16) | 419 ((buf[o+3] & 0xff) << 24) | 420 ((buf[o+4] & 0xffL) << 32) | 421 ((long)(buf[o+5]) << 40); 422 break; 423 case 5: 424 result = (buf[o] & 0xff) | 425 ((buf[o+1] & 0xff) << 8) | 426 ((buf[o+2] & 0xff) << 16) | 427 ((buf[o+3] & 0xff) << 24) | 428 ((long)(buf[o+4]) << 32); 429 break; 430 case 4: 431 result = (buf[o] & 0xff) | 432 ((buf[o+1] & 0xff) << 8) | 433 ((buf[o+2] & 0xff) << 16) | 434 (buf[o+3] << 24); 435 break; 436 case 3: 437 result = (buf[o] & 0xff) << 8 | 438 ((buf[o+1] & 0xff) << 16) | 439 (buf[o+2] << 24); 440 break; 441 case 2: 442 result = (buf[o] & 0xff) << 16 | 443 (buf[o+1] << 24); 444 break; 445 case 1: 446 result = buf[o] << 24; 447 break; 448 default: 449 throw new ExceptionWithContext("Invalid size %d for sized long at offset 0x%x", bytes, offset); 450 } 451 452 o += bytes; 453 return result; 454 } 455}