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