DexReader.java revision ebd617800870433d4133a192bac709c645b55a9b
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 readUshort() { 191 int o = offset; 192 int result = dexBuf.readUshort(offset); 193 offset = o + 2; 194 return result; 195 } 196 197 public int readUbyte() { 198 int o = offset; 199 int result = dexBuf.readUbyte(offset); 200 offset = o + 1; 201 return result; 202 } 203 204 public long readLong() { 205 int o = offset; 206 long result = dexBuf.readLong(offset); 207 offset = o + 8; 208 return result; 209 } 210 211 public int readInt() { 212 int o = offset; 213 int result = dexBuf.readInt(offset); 214 offset = o + 4; 215 return result; 216 } 217 218 public int readShort() { 219 int o = offset; 220 int result = dexBuf.readShort(offset); 221 offset = o + 2; 222 return result; 223 } 224 225 public int readByte() { 226 int o = offset; 227 int result = dexBuf.readByte(offset); 228 offset = o + 1; 229 return result; 230 } 231 232 public void skipByte() { offset++; } 233 public void moveRelative(int i) { offset += i; } 234 235 public int readSmallUint(int offset) { return dexBuf.readSmallUint(offset); } 236 public int readUshort(int offset) { return dexBuf.readUshort(offset); } 237 public int readUbyte(int offset) { return dexBuf.readUbyte(offset); } 238 public long readLong(int offset) { return dexBuf.readLong(offset); } 239 public int readInt(int offset) { return dexBuf.readInt(offset); } 240 public int readShort(int offset) { return dexBuf.readShort(offset); } 241 public int readByte(int offset) { return dexBuf.readByte(offset); } 242 243 public int readSizedInt(int bytes) { 244 int o = offset; 245 byte[] buf = dexBuf.buf; 246 247 int result; 248 switch (bytes) { 249 case 4: 250 result = (buf[o] & 0xff) | 251 ((buf[o+1] & 0xff) << 8) | 252 ((buf[o+2] & 0xff) << 16) | 253 (buf[o+3] << 24); 254 break; 255 case 3: 256 result = (buf[o] & 0xff) | 257 ((buf[o+1] & 0xff) << 8) | 258 ((buf[o+2]) << 16); 259 break; 260 case 2: 261 result = (buf[o] & 0xff) | 262 ((buf[o+1]) << 8); 263 break; 264 case 1: 265 result = buf[o]; 266 break; 267 default: 268 throw new ExceptionWithContext("Invalid size %d for sized int at offset 0x%x", bytes, offset); 269 } 270 offset = o + bytes; 271 return result; 272 } 273 274 public int readSizedSmallUint(int bytes) { 275 int o = offset; 276 byte[] buf = dexBuf.buf; 277 278 int result = 0; 279 switch (bytes) { 280 case 4: 281 int b = buf[o+3]; 282 if (b < 0) { 283 throw new ExceptionWithContext( 284 "Encountered valid sized uint that is out of range at offset 0x%x", offset); 285 } 286 result = b << 24; 287 // fall-through 288 case 3: 289 result |= (buf[o+2] & 0xff) << 16; 290 // fall-through 291 case 2: 292 result |= (buf[o+1] & 0xff) << 8; 293 // fall-through 294 case 1: 295 result |= (buf[o] & 0xff); 296 break; 297 default: 298 throw new ExceptionWithContext("Invalid size %d for sized uint at offset 0x%x", bytes, offset); 299 } 300 offset = o + bytes; 301 return result; 302 } 303 304 public int readSizedRightExtendedInt(int bytes) { 305 int o = offset; 306 byte[] buf = dexBuf.buf; 307 308 int result; 309 switch (bytes) { 310 case 4: 311 result = (buf[o] & 0xff) | 312 ((buf[o+1] & 0xff) << 8) | 313 ((buf[o+2] & 0xff) << 16) | 314 (buf[o+3] << 24); 315 break; 316 case 3: 317 result = (buf[o] & 0xff) << 8 | 318 ((buf[o+1] & 0xff) << 16) | 319 (buf[o+2] << 24); 320 break; 321 case 2: 322 result = (buf[o] & 0xff) << 16 | 323 (buf[o+1] << 24); 324 break; 325 case 1: 326 result = buf[o] << 24; 327 break; 328 default: 329 throw new ExceptionWithContext( 330 "Invalid size %d for sized, right extended int at offset 0x%x", bytes, offset); 331 } 332 offset = o + bytes; 333 return result; 334 } 335 336 public long readSizedRightExtendedLong(int bytes) { 337 int o = offset; 338 byte[] buf = dexBuf.buf; 339 340 long result; 341 switch (bytes) { 342 case 8: 343 result = (buf[o] & 0xff) | 344 ((buf[o+1] & 0xff) << 8) | 345 ((buf[o+2] & 0xff) << 16) | 346 ((buf[o+3] & 0xffL) << 24) | 347 ((buf[o+4] & 0xffL) << 32) | 348 ((buf[o+5] & 0xffL) << 40) | 349 ((buf[o+6] & 0xffL) << 48) | 350 (((long)buf[o+7]) << 56); 351 break; 352 case 7: 353 result = ((buf[o] & 0xff)) << 8 | 354 ((buf[o+1] & 0xff) << 16) | 355 ((buf[o+2] & 0xffL) << 24) | 356 ((buf[o+3] & 0xffL) << 32) | 357 ((buf[o+4] & 0xffL) << 40) | 358 ((buf[o+5] & 0xffL) << 48) | 359 (((long)buf[o+6]) << 56); 360 break; 361 case 6: 362 result = ((buf[o] & 0xff)) << 16 | 363 ((buf[o+1] & 0xffL) << 24) | 364 ((buf[o+2] & 0xffL) << 32) | 365 ((buf[o+3] & 0xffL) << 40) | 366 ((buf[o+4] & 0xffL) << 48) | 367 (((long)buf[o+5]) << 56); 368 break; 369 case 5: 370 result = ((buf[o] & 0xffL)) << 24 | 371 ((buf[o+1] & 0xffL) << 32) | 372 ((buf[o+2] & 0xffL) << 40) | 373 ((buf[o+3] & 0xffL) << 48) | 374 (((long)buf[o+4]) << 56); 375 break; 376 case 4: 377 result = ((buf[o] & 0xffL)) << 32 | 378 ((buf[o+1] & 0xffL) << 40) | 379 ((buf[o+2] & 0xffL) << 48) | 380 (((long)buf[o+3]) << 56); 381 break; 382 case 3: 383 result = ((buf[o] & 0xffL)) << 40 | 384 ((buf[o+1] & 0xffL) << 48) | 385 (((long)buf[o+2]) << 56); 386 break; 387 case 2: 388 result = ((buf[o] & 0xffL)) << 48 | 389 (((long)buf[o+1]) << 56); 390 break; 391 case 1: 392 result = ((long)buf[o]) << 56; 393 break; 394 default: 395 throw new ExceptionWithContext( 396 "Invalid size %d for sized, right extended long at offset 0x%x", bytes, offset); 397 } 398 offset = o + bytes; 399 return result; 400 } 401 402 public long readSizedLong(int bytes) { 403 int o = offset; 404 byte[] buf = dexBuf.buf; 405 406 long result; 407 switch (bytes) { 408 case 8: 409 result = (buf[o] & 0xff) | 410 ((buf[o+1] & 0xff) << 8) | 411 ((buf[o+2] & 0xff) << 16) | 412 ((buf[o+3] & 0xffL) << 24) | 413 ((buf[o+4] & 0xffL) << 32) | 414 ((buf[o+5] & 0xffL) << 40) | 415 ((buf[o+6] & 0xffL) << 48) | 416 (((long)buf[o+7]) << 56); 417 break; 418 case 7: 419 result = (buf[o] & 0xff) | 420 ((buf[o+1] & 0xff) << 8) | 421 ((buf[o+2] & 0xff) << 16) | 422 ((buf[o+3] & 0xffL) << 24) | 423 ((buf[o+4] & 0xffL) << 32) | 424 ((buf[o+5] & 0xffL) << 40) | 425 ((long)(buf[o+6]) << 48); 426 break; 427 case 6: 428 result = (buf[o] & 0xff) | 429 ((buf[o+1] & 0xff) << 8) | 430 ((buf[o+2] & 0xff) << 16) | 431 ((buf[o+3] & 0xffL) << 24) | 432 ((buf[o+4] & 0xffL) << 32) | 433 ((long)(buf[o+5]) << 40); 434 break; 435 case 5: 436 result = (buf[o] & 0xff) | 437 ((buf[o+1] & 0xff) << 8) | 438 ((buf[o+2] & 0xff) << 16) | 439 ((buf[o+3] & 0xffL) << 24) | 440 ((long)(buf[o+4]) << 32); 441 break; 442 case 4: 443 result = (buf[o] & 0xff) | 444 ((buf[o+1] & 0xff) << 8) | 445 ((buf[o+2] & 0xff) << 16) | 446 (((long)buf[o+3]) << 24); 447 break; 448 case 3: 449 result = (buf[o] & 0xff) | 450 ((buf[o+1] & 0xff) << 8) | 451 (buf[o+2] << 16); 452 break; 453 case 2: 454 result = (buf[o] & 0xff) | 455 (buf[o+1] << 8); 456 break; 457 case 1: 458 result = buf[o]; 459 break; 460 default: 461 throw new ExceptionWithContext("Invalid size %d for sized long at offset 0x%x", bytes, offset); 462 } 463 464 o += bytes; 465 return result; 466 } 467}