1959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle/* 2959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Copyright (C) 2014 The Android Open Source Project 3959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * 4959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Licensed under the Apache License, Version 2.0 (the "License"); 5959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * you may not use this file except in compliance with the License. 6959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * You may obtain a copy of the License at 7959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * 8959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * http://www.apache.org/licenses/LICENSE-2.0 9959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * 10959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Unless required by applicable law or agreed to in writing, software 11959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * distributed under the License is distributed on an "AS IS" BASIS, 12959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * See the License for the specific language governing permissions and 14959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * limitations under the License. 15959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 16959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 17959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepackage dexfuzz.rawdex; 18959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 19959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.Log; 20959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 21959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.io.FileNotFoundException; 22959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.io.IOException; 23959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.io.RandomAccessFile; 24959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 25959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle/** 26959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * An extension to RandomAccessFile that allows reading/writing 27959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * DEX files in little-endian form, the variable-length LEB format 28959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * and also provides word-alignment functions. 29959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 30959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepublic class DexRandomAccessFile extends RandomAccessFile { 31959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private OffsetTracker offsetTracker; 32959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 33959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public OffsetTracker getOffsetTracker() { 34959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return offsetTracker; 35959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 36959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 37959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void setOffsetTracker(OffsetTracker offsetTracker) { 38959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle this.offsetTracker = offsetTracker; 39959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 40959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 41959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 42959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Constructor, passes straight on to RandomAccessFile currently. 43959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * @param filename The file to open. 44959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * @param mode Strings "r" or "rw" work best. 45959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 46959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public DexRandomAccessFile(String filename, String mode) 47959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle throws FileNotFoundException { 48959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle super(filename, mode); 49959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 50959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 51959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 52959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * @return A 16-bit number, read from the file as little-endian. 53959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 54959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public short readUShort() throws IOException { 55959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int b1 = readUnsignedByte(); 56959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int b2 = readUnsignedByte(); 57959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return (short) ((b2 << 8) | b1); 58959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 59959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 60959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 61959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * @param value A 16-bit number to be written to the file in little-endian. 62959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 63959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void writeUShort(short value) throws IOException { 64959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int b1 = value & 0xff; 65959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int b2 = (value & 0xff00) >> 8; 66959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(b1); 67959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(b2); 68959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 69959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 70959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 71959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * @return A 32-bit number, read from the file as little-endian. 72959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 73959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public int readUInt() throws IOException { 74959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int b1 = readUnsignedByte(); 75959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int b2 = readUnsignedByte(); 76959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int b3 = readUnsignedByte(); 77959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int b4 = readUnsignedByte(); 78959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1; 79959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 80959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 81959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 82959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * @param value A 32-bit number to be written to the file in little-endian. 83959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 84959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void writeUInt(int value) throws IOException { 85959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int b1 = value & 0xff; 86959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(b1); 87959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int b2 = (value & 0xff00) >> 8; 88959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(b2); 89959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int b3 = (value & 0xff0000) >> 16; 90959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(b3); 91959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int b4 = (value & 0xff000000) >> 24; 92959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(b4); 93959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 94959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 95959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 96959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * @return An up to 32-bit number, read from the file in ULEB128 form. 97959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 98959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public int readUleb128() throws IOException { 99959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int shift = 0; 100959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int value = 0; 101959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int rawByte = readUnsignedByte(); 102959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle boolean done = false; 103959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle while (!done) { 104959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Get the lower seven bits. 105959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // 0x7f = 0111 1111 106959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle value |= ((rawByte & 0x7f) << shift); 107959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle shift += 7; 108959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Check the 8th bit - if it's 0, we're done. 109959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // 0x80 = 1000 0000 110959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if ((rawByte & 0x80) == 0) { 111959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle done = true; 112959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else { 113959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle rawByte = readUnsignedByte(); 114959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 115959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 116959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return value; 117959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 118959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 119959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 120959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * @param value A 32-bit number to be written to the file in ULEB128 form. 121959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 122959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void writeUleb128(int value) throws IOException { 123959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (value == 0) { 124959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(0); 125959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return; 126959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 127959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 128959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle while (value != 0) { 129959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int marker = 1; 130959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // If we're down to the last 7 bits, the marker will be 0. 131959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if ((value & 0xffffff80) == 0) { 132959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle marker = 0; 133959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 134959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Get the lowest 7 bits, add on the marker in the high bit. 135959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int nextByte = value & 0x7f | (marker << 7); 136959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(nextByte); 137959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle value >>>= 7; 138959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 139959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 140959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 141959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 142959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Write out ULEB128 value always using 5 bytes. 143959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * A version of ULEB128 that will always write out 5 bytes, because this 144959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * value will be patched later, and if we used a smaller encoding, the new value 145959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * may overflow the previously selected encoding size. 146959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * The largest encoding for 0 in ULEB128 would be: 147959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * 0x80 0x80 0x80 0x80 0x00 148959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * and for 1 would be: 149959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * 0x81 0x80 0x80 0x80 0x00 150959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 151959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void writeLargestUleb128(int value) throws IOException { 152959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.debug("Writing " + value + " using the largest possible ULEB128 encoding."); 153959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (value == 0) { 154959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(0x80); 155959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(0x80); 156959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(0x80); 157959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(0x80); 158959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(0x0); 159959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return; 160959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 161959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 162959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (int i = 0; i < 5; i++) { 163959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int marker = 1; 164959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // If we're writing the 5th byte, the marker is 0. 165959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (i == 4) { 166959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle marker = 0; 167959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 168959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Get the lowest 7 bits, add on the marker in the high bit. 169959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int nextByte = value & 0x7f | (marker << 7); 170959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(nextByte); 171959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle value >>>= 7; 172959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 173959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 174959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 175959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 176959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * @return An up to 32-bit number, read from the file in SLEB128 form. 177959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 178959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public int readSleb128() throws IOException { 179959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int shift = 0; 180959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int value = 0; 181959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int rawByte = readUnsignedByte(); 182959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle boolean done = false; 183959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle boolean mustSignExtend = false; 184959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle while (!done) { 185959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Get the lower seven bits. 186959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // 0x7f = 0111 1111 187959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle value |= ((rawByte & 0x7f) << shift); 188959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle shift += 7; 189959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Check the 8th bit - if it's 0, we're done. 190959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // 0x80 = 1000 0000 191959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if ((rawByte & 0x80) == 0) { 192959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Check the 7th bit - if it's a 1, we need to sign extend. 193959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if ((rawByte & 0x60) != 0) { 194959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mustSignExtend = true; 195959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 196959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle done = true; 197959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else { 198959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle rawByte = readUnsignedByte(); 199959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 200959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 201959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mustSignExtend) { 202959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Example: 203959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // say we shifted 7 bits, we need 204959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // to make all the upper 25 bits 1s. 205959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // load a 1... 206959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // 00000000 00000000 00000000 00000001 207959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // << 7 208959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // 00000000 00000000 00000000 10000000 209959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // - 1 210959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // 00000000 00000000 00000000 01111111 211959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // ~ 212959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // 11111111 11111111 11111111 10000000 213959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int upperOnes = ~((1 << shift) - 1); 214959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle value |= (upperOnes); 215959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 216959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return value; 217959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 218959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 219959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 220959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * @param value A 32-bit number to be written to the file in SLEB128 form. 221959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 222959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void writeSleb128(int value) throws IOException { 223959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (value == 0) { 224959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(0); 225959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return; 226959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 227959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (value > 0) { 228959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeUleb128(value); 229959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return; 230959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 231959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (value == -1) { 232959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(0x7f); 233959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 234959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 235959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // When it's all 1s (0xffffffff), we're done! 236959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle while (value != 0xffffffff) { 237959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int marker = 1; 238959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // If we're down to the last 7 bits (i.e., shifting a further 7 is all 1s), 239959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // the marker will be 0. 240959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if ((value >> 7) == 0xffffffff) { 241959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle marker = 0; 242959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 243959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Get the lowest 7 bits, add on the marker in the high bit. 244959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int nextByte = value & 0x7f | (marker << 7); 245959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(nextByte); 246959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle value >>= 7; 247959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 248959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 249959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 250959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 251959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * In DEX format, strings are in MUTF-8 format, the first ULEB128 value is the decoded size 252959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * (i.e., string.length), and then follows a null-terminated series of characters. 253959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * @param decodedSize The ULEB128 value that should have been read just before this. 254959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * @return The raw bytes of the string, not including the null character. 255959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 256959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public byte[] readDexUtf(int decodedSize) throws IOException { 257959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // In the dex MUTF-8, the encoded size can never be larger than 3 times 258959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // the actual string's length (which is the ULEB128 value just before this 259959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // string, the "decoded size") 260959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 261959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Therefore, allocate as much space as we might need. 262959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle byte[] str = new byte[decodedSize * 3]; 263959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 264959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Get our first byte. 265959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int encodedSize = 0; 266959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle byte rawByte = readByte(); 267959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 268959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Keep reading until we find the end marker. 269959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle while (rawByte != 0) { 270959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle str[encodedSize++] = rawByte; 271959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle rawByte = readByte(); 272959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 273959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 274959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Copy everything we read into str into the correctly-sized actual string. 275959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle byte[] actualString = new byte[encodedSize]; 276959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (int i = 0; i < encodedSize; i++) { 277959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle actualString[i] = str[i]; 278959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 279959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 280959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return actualString; 281959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 282959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 283959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 284959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Writes out raw bytes that would have been read by readDexUTF(). 285959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Will automatically write out the null-byte at the end. 286959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * @param data Bytes to be written out. 287959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 288959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void writeDexUtf(byte[] data) throws IOException { 289959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle write(data); 290959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Remember to add the end marker. 291959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle writeByte(0); 292959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 293959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 294959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 295959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Align the file handle's seek pointer to the next N bytes. 296959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * @param alignment N to align to. 297959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 298959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void alignForwards(int alignment) throws IOException { 299959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle long offset = getFilePointer(); 300959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle long mask = alignment - 1; 301959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if ((offset & mask) != 0) { 302959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int extra = alignment - (int) (offset & mask); 303959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle seek(offset + extra); 304959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 305959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 306959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 307959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 308959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Align the file handle's seek pointer backwards to the previous N bytes. 309959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * @param alignment N to align to. 310959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 311959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void alignBackwards(int alignment) throws IOException { 312959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle long offset = getFilePointer(); 313959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle long mask = alignment - 1; 314959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if ((offset & mask) != 0) { 315959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle offset &= (~mask); 316959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle seek(offset); 317959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 318959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 319959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle} 320