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