DexReader.java revision b116cb0ac9c9da172ab8224a7eb762dbbbb9bed1
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 public void setOffset(int offset) { this.offset = offset; } 50 51 public int getStringIdItemOffset(int stringIndex) { return dexBuf.getStringIdItemOffset(stringIndex); } 52 public int getTypeIdItemOffset(int typeIndex) { return dexBuf.getTypeIdItemOffset(typeIndex); } 53 public int getFieldIdItemOffset(int fieldIndex) { return dexBuf.getFieldIdItemOffset(fieldIndex); } 54 public int getMethodIdItemOffset(int methodIndex) { return dexBuf.getMethodIdItemOffset(methodIndex); } 55 public int getProtoIdItemOffset(int methodIndex) { return dexBuf.getProtoIdItemOffset(methodIndex); } 56 public int getClassDefItemOffset(int classIndex) { return dexBuf.getClassDefItemOffset(classIndex); } 57 public String getString(int stringIndex) { return dexBuf.getString(stringIndex); } 58 public String getOptionalString(int stringIndex) { return dexBuf.getOptionalString(stringIndex); } 59 public String getType(int typeIndex) { return dexBuf.getType(typeIndex); } 60 public String getOptionalType(int typeIndex) { return dexBuf.getOptionalType(typeIndex); } 61 public String getField(int fieldIndex) { return dexBuf.getField(fieldIndex); } 62 public String getMethod(int methodIndex) { return dexBuf.getMethod(methodIndex); } 63 public String getReference(int type, int index) { return dexBuf.getReference(type, index); } 64 65 /** {@inheritDoc} */ 66 public int readSleb128() { 67 int end = offset; 68 int currentByteValue; 69 int result; 70 byte[] buf = dexBuf.buf; 71 72 result = buf[end++] & 0xff; 73 if (result <= 0x7f) { 74 result = (result << 25) >> 25; 75 } else { 76 currentByteValue = buf[end++] & 0xff; 77 result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7); 78 if (currentByteValue <= 0x7f) { 79 result = (result << 18) >> 18; 80 } else { 81 currentByteValue = buf[end++] & 0xff; 82 result |= (currentByteValue & 0x7f) << 14; 83 if (currentByteValue <= 0x7f) { 84 result = (result << 11) >> 11; 85 } else { 86 currentByteValue = buf[end++] & 0xff; 87 result |= (currentByteValue & 0x7f) << 21; 88 if (currentByteValue <= 0x7f) { 89 result = (result << 4) >> 4; 90 } else { 91 currentByteValue = buf[end++] & 0xff; 92 if (currentByteValue > 0x7f) { 93 throw new ExceptionWithContext( 94 "Invalid sleb128 integer encountered at offset 0x%x", offset); 95 } 96 result |= currentByteValue << 28; 97 } 98 } 99 } 100 } 101 102 offset = end; 103 return result; 104 } 105 106 public int readSmallUleb128() { 107 int end = offset; 108 int currentByteValue; 109 int result; 110 byte[] buf = dexBuf.buf; 111 112 result = buf[end++] & 0xff; 113 if (result > 0x7f) { 114 currentByteValue = buf[end++] & 0xff; 115 result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7); 116 if (currentByteValue > 0x7f) { 117 currentByteValue = buf[end++] & 0xff; 118 result |= (currentByteValue & 0x7f) << 14; 119 if (currentByteValue > 0x7f) { 120 currentByteValue = buf[end++] & 0xff; 121 result |= (currentByteValue & 0x7f) << 21; 122 if (currentByteValue > 0x7f) { 123 currentByteValue = buf[end++]; 124 125 // MSB shouldn't be set on last byte 126 if (currentByteValue < 0) { 127 throw new ExceptionWithContext( 128 "Invalid uleb128 integer encountered at offset 0x%x", offset); 129 } else if ((currentByteValue & 0xf) > 0x07) { 130 // we assume most significant bit of the result will not be set, so that it can fit into 131 // a signed integer without wrapping 132 throw new ExceptionWithContext( 133 "Encountered valid uleb128 that is out of range at offset 0x%x", offset); 134 } 135 result |= currentByteValue << 28; 136 } 137 } 138 } 139 } 140 141 offset = end; 142 return result; 143 } 144 145 public void skipUleb128() { 146 int end = offset; 147 byte currentByteValue; 148 byte[] buf = dexBuf.buf; 149 150 currentByteValue = buf[end++]; 151 if (currentByteValue < 0) { // if the MSB is set 152 currentByteValue = buf[end++]; 153 if (currentByteValue < 0) { // if the MSB is set 154 currentByteValue = buf[end++]; 155 if (currentByteValue < 0) { // if the MSB is set 156 currentByteValue = buf[end++]; 157 if (currentByteValue < 0) { // if the MSB is set 158 currentByteValue = buf[end++]; 159 if (currentByteValue < 0) { 160 throw new ExceptionWithContext( 161 "Invalid uleb128 integer encountered at offset 0x%x", offset); 162 } else if ((currentByteValue & 0xf) > 0x07) { 163 // we assume most significant bit of the result will not be set, so that it can fit into 164 // a signed integer without wrapping 165 throw new ExceptionWithContext( 166 "Encountered valid uleb128 that is out of range at offset 0x%x", offset); 167 } 168 } 169 } 170 } 171 } 172 173 offset = end; 174 } 175 176 public int readSmallUint() { 177 int o = offset; 178 int result = dexBuf.readSmallUint(o); 179 offset = o + 4; 180 return result; 181 } 182 183 public int readOptionalUint() { 184 int o = offset; 185 int result = dexBuf.readOptionalUint(o); 186 offset = o + 4; 187 return result; 188 } 189 190 public int peekUshort() { 191 return dexBuf.readUshort(offset); 192 } 193 194 public int readUshort() { 195 int o = offset; 196 int result = dexBuf.readUshort(offset); 197 offset = o + 2; 198 return result; 199 } 200 201 public int peekUbyte() { 202 return dexBuf.readUbyte(offset); 203 } 204 205 public int readUbyte() { 206 int o = offset; 207 int result = dexBuf.readUbyte(offset); 208 offset = o + 1; 209 return result; 210 } 211 212 public long readLong() { 213 int o = offset; 214 long result = dexBuf.readLong(offset); 215 offset = o + 8; 216 return result; 217 } 218 219 public int readInt() { 220 int o = offset; 221 int result = dexBuf.readInt(offset); 222 offset = o + 4; 223 return result; 224 } 225 226 public int readShort() { 227 int o = offset; 228 int result = dexBuf.readShort(offset); 229 offset = o + 2; 230 return result; 231 } 232 233 public int readByte() { 234 int o = offset; 235 int result = dexBuf.readByte(offset); 236 offset = o + 1; 237 return result; 238 } 239 240 public void skipByte() { offset++; } 241 public void moveRelative(int i) { offset += i; } 242 243 public int readSmallUint(int offset) { return dexBuf.readSmallUint(offset); } 244 public int readUshort(int offset) { return dexBuf.readUshort(offset); } 245 public int readUbyte(int offset) { return dexBuf.readUbyte(offset); } 246 public long readLong(int offset) { return dexBuf.readLong(offset); } 247 public int readInt(int offset) { return dexBuf.readInt(offset); } 248 public int readShort(int offset) { return dexBuf.readShort(offset); } 249 public int readByte(int offset) { return dexBuf.readByte(offset); } 250 251 public int readSizedInt(int bytes) { 252 int o = offset; 253 byte[] buf = dexBuf.buf; 254 255 int result; 256 switch (bytes) { 257 case 4: 258 result = (buf[o] & 0xff) | 259 ((buf[o+1] & 0xff) << 8) | 260 ((buf[o+2] & 0xff) << 16) | 261 (buf[o+3] << 24); 262 break; 263 case 3: 264 result = (buf[o] & 0xff) | 265 ((buf[o+1] & 0xff) << 8) | 266 ((buf[o+2]) << 16); 267 break; 268 case 2: 269 result = (buf[o] & 0xff) | 270 ((buf[o+1]) << 8); 271 break; 272 case 1: 273 result = buf[o]; 274 break; 275 default: 276 throw new ExceptionWithContext("Invalid size %d for sized int at offset 0x%x", bytes, offset); 277 } 278 offset = o + bytes; 279 return result; 280 } 281 282 public int readSizedSmallUint(int bytes) { 283 int o = offset; 284 byte[] buf = dexBuf.buf; 285 286 int result = 0; 287 switch (bytes) { 288 case 4: 289 int b = buf[o+3]; 290 if (b < 0) { 291 throw new ExceptionWithContext( 292 "Encountered valid sized uint that is out of range at offset 0x%x", offset); 293 } 294 result = b << 24; 295 // fall-through 296 case 3: 297 result |= (buf[o+2] & 0xff) << 16; 298 // fall-through 299 case 2: 300 result |= (buf[o+1] & 0xff) << 8; 301 // fall-through 302 case 1: 303 result |= (buf[o] & 0xff); 304 break; 305 default: 306 throw new ExceptionWithContext("Invalid size %d for sized uint at offset 0x%x", bytes, offset); 307 } 308 offset = o + bytes; 309 return result; 310 } 311 312 public int readSizedRightExtendedInt(int bytes) { 313 int o = offset; 314 byte[] buf = dexBuf.buf; 315 316 int result; 317 switch (bytes) { 318 case 4: 319 result = (buf[o] & 0xff) | 320 ((buf[o+1] & 0xff) << 8) | 321 ((buf[o+2] & 0xff) << 16) | 322 (buf[o+3] << 24); 323 break; 324 case 3: 325 result = (buf[o] & 0xff) << 8 | 326 ((buf[o+1] & 0xff) << 16) | 327 (buf[o+2] << 24); 328 break; 329 case 2: 330 result = (buf[o] & 0xff) << 16 | 331 (buf[o+1] << 24); 332 break; 333 case 1: 334 result = buf[o] << 24; 335 break; 336 default: 337 throw new ExceptionWithContext( 338 "Invalid size %d for sized, right extended int at offset 0x%x", bytes, offset); 339 } 340 offset = o + bytes; 341 return result; 342 } 343 344 public long readSizedRightExtendedLong(int bytes) { 345 int o = offset; 346 byte[] buf = dexBuf.buf; 347 348 long result; 349 switch (bytes) { 350 case 8: 351 result = (buf[o] & 0xff) | 352 ((buf[o+1] & 0xff) << 8) | 353 ((buf[o+2] & 0xff) << 16) | 354 ((buf[o+3] & 0xffL) << 24) | 355 ((buf[o+4] & 0xffL) << 32) | 356 ((buf[o+5] & 0xffL) << 40) | 357 ((buf[o+6] & 0xffL) << 48) | 358 (((long)buf[o+7]) << 56); 359 break; 360 case 7: 361 result = ((buf[o] & 0xff)) << 8 | 362 ((buf[o+1] & 0xff) << 16) | 363 ((buf[o+2] & 0xffL) << 24) | 364 ((buf[o+3] & 0xffL) << 32) | 365 ((buf[o+4] & 0xffL) << 40) | 366 ((buf[o+5] & 0xffL) << 48) | 367 (((long)buf[o+6]) << 56); 368 break; 369 case 6: 370 result = ((buf[o] & 0xff)) << 16 | 371 ((buf[o+1] & 0xffL) << 24) | 372 ((buf[o+2] & 0xffL) << 32) | 373 ((buf[o+3] & 0xffL) << 40) | 374 ((buf[o+4] & 0xffL) << 48) | 375 (((long)buf[o+5]) << 56); 376 break; 377 case 5: 378 result = ((buf[o] & 0xffL)) << 24 | 379 ((buf[o+1] & 0xffL) << 32) | 380 ((buf[o+2] & 0xffL) << 40) | 381 ((buf[o+3] & 0xffL) << 48) | 382 (((long)buf[o+4]) << 56); 383 break; 384 case 4: 385 result = ((buf[o] & 0xffL)) << 32 | 386 ((buf[o+1] & 0xffL) << 40) | 387 ((buf[o+2] & 0xffL) << 48) | 388 (((long)buf[o+3]) << 56); 389 break; 390 case 3: 391 result = ((buf[o] & 0xffL)) << 40 | 392 ((buf[o+1] & 0xffL) << 48) | 393 (((long)buf[o+2]) << 56); 394 break; 395 case 2: 396 result = ((buf[o] & 0xffL)) << 48 | 397 (((long)buf[o+1]) << 56); 398 break; 399 case 1: 400 result = ((long)buf[o]) << 56; 401 break; 402 default: 403 throw new ExceptionWithContext( 404 "Invalid size %d for sized, right extended long at offset 0x%x", bytes, offset); 405 } 406 offset = o + bytes; 407 return result; 408 } 409 410 public long readSizedLong(int bytes) { 411 int o = offset; 412 byte[] buf = dexBuf.buf; 413 414 long result; 415 switch (bytes) { 416 case 8: 417 result = (buf[o] & 0xff) | 418 ((buf[o+1] & 0xff) << 8) | 419 ((buf[o+2] & 0xff) << 16) | 420 ((buf[o+3] & 0xffL) << 24) | 421 ((buf[o+4] & 0xffL) << 32) | 422 ((buf[o+5] & 0xffL) << 40) | 423 ((buf[o+6] & 0xffL) << 48) | 424 (((long)buf[o+7]) << 56); 425 break; 426 case 7: 427 result = (buf[o] & 0xff) | 428 ((buf[o+1] & 0xff) << 8) | 429 ((buf[o+2] & 0xff) << 16) | 430 ((buf[o+3] & 0xffL) << 24) | 431 ((buf[o+4] & 0xffL) << 32) | 432 ((buf[o+5] & 0xffL) << 40) | 433 ((long)(buf[o+6]) << 48); 434 break; 435 case 6: 436 result = (buf[o] & 0xff) | 437 ((buf[o+1] & 0xff) << 8) | 438 ((buf[o+2] & 0xff) << 16) | 439 ((buf[o+3] & 0xffL) << 24) | 440 ((buf[o+4] & 0xffL) << 32) | 441 ((long)(buf[o+5]) << 40); 442 break; 443 case 5: 444 result = (buf[o] & 0xff) | 445 ((buf[o+1] & 0xff) << 8) | 446 ((buf[o+2] & 0xff) << 16) | 447 ((buf[o+3] & 0xffL) << 24) | 448 ((long)(buf[o+4]) << 32); 449 break; 450 case 4: 451 result = (buf[o] & 0xff) | 452 ((buf[o+1] & 0xff) << 8) | 453 ((buf[o+2] & 0xff) << 16) | 454 (((long)buf[o+3]) << 24); 455 break; 456 case 3: 457 result = (buf[o] & 0xff) | 458 ((buf[o+1] & 0xff) << 8) | 459 (buf[o+2] << 16); 460 break; 461 case 2: 462 result = (buf[o] & 0xff) | 463 (buf[o+1] << 8); 464 break; 465 case 1: 466 result = buf[o]; 467 break; 468 default: 469 throw new ExceptionWithContext("Invalid size %d for sized long at offset 0x%x", bytes, offset); 470 } 471 472 offset = o + bytes; 473 return result; 474 } 475}