private Field[] ReadFields(ulong count, BinaryReader reader, Dictionary <uint, List <Annotation> > annotations) { var fields = new Field[count]; long position = 0; ulong currentFieldIndex = 0; for (ulong index = 0; index < count; index++) { currentFieldIndex += Leb128.ReadUleb(reader); var accessFlags = Leb128.ReadUleb(reader); position = reader.BaseStream.Position; var field = Dex.GetField((uint)currentFieldIndex); field.AccessFlags = (AccessFlag)accessFlags; List <Annotation> annotation = null; annotations.TryGetValue((uint)currentFieldIndex, out annotation); if (annotation != null) { field.Annotations = annotation; } fields[index] = field; reader.BaseStream.Position = position; } return(fields); }
internal EncodedArray(BinaryReader reader) { Count = Leb128.ReadUleb(reader); EncodedValues = new EncodedValue[Count]; for (ulong i = 0; i < Count; i++) { EncodedValues[i] = EncodedValue.parse(reader); } }
public EncodedAnnotation(BinaryReader reader) { AnnotationType = Leb128.ReadUleb(reader); var size = Leb128.ReadUleb(reader); Elements = new AnnotationElement[size]; for (ulong i = 0; i < size; i++) { Elements[i] = new AnnotationElement(reader); } }
private Method[] ReadMethods(ulong count, BinaryReader reader, Dictionary <uint, List <Annotation> > annotations, Dictionary <uint, List <Annotation> > parameterAnnotations) { var methods = new Method[count]; long position = 0; ulong currentMethodIndex = 0; for (ulong currentMethod = 0; currentMethod < count; currentMethod++) { currentMethodIndex += Leb128.ReadUleb(reader); var accessFlags = Leb128.ReadUleb(reader); var codeOffset = (uint)Leb128.ReadUleb(reader); position = reader.BaseStream.Position; var method = Dex.GetMethod((uint)currentMethodIndex, codeOffset); method.AccessFlags = accessFlags; List <Annotation> annotation = null; annotations.TryGetValue((uint)currentMethodIndex, out annotation); if (annotation != null) { method.Annotations = annotation; } List <Annotation> parameterAnnotation = null; parameterAnnotations.TryGetValue((uint)currentMethodIndex, out parameterAnnotation); if (parameterAnnotation != null) { method.ParameterAnnotations = parameterAnnotation; } methods[currentMethod] = method; reader.BaseStream.Position = position; } return(methods); }
/// <summary> /// Constructor /// </summary> /// <param name='dex'> /// Pointer to the DEX file this class was loaded from /// </param> internal Class(Dex dex, BinaryReader reader) { Dex = dex; ClassIndex = reader.ReadUInt32(); AccessFlags = (AccessFlag)reader.ReadUInt32(); SuperClassIndex = reader.ReadUInt32(); var interfacesOffset = reader.ReadUInt32(); SourceFileIndex = reader.ReadUInt32(); var annotationsOffset = reader.ReadUInt32(); var classDataOffset = reader.ReadUInt32(); var staticValuesOffset = reader.ReadUInt32(); Interfaces = dex.ReadTypeList(interfacesOffset); var fieldAnnotations = new Dictionary <uint, List <Annotation> >(); var methodAnnotations = new Dictionary <uint, List <Annotation> >(); var parameterAnnotations = new Dictionary <uint, List <Annotation> >(); if (annotationsOffset != 0) { reader.BaseStream.Position = annotationsOffset; // annotations_directory_item var classAnnotationsOffset = reader.ReadUInt32(); var annotatedFieldsCount = reader.ReadUInt32(); var annotatedMethodsCount = reader.ReadUInt32(); var annotatedParametersCount = reader.ReadUInt32(); for (int i = 0; i < annotatedFieldsCount; i++) { // field_annotation var fieldIndex = reader.ReadUInt32(); var annotations = Annotation.ReadAnnotations(reader); fieldAnnotations.Add(fieldIndex, annotations); } for (int i = 0; i < annotatedMethodsCount; i++) { // method_annotation var methodIndex = reader.ReadUInt32(); var annotations = Annotation.ReadAnnotations(reader); methodAnnotations.Add(methodIndex, annotations); } for (int i = 0; i < annotatedParametersCount; i++) { // parameter_annotation var methodIndex = reader.ReadUInt32(); var annotations = Annotation.ReadAnnotations(reader); parameterAnnotations.Add(methodIndex, annotations); } if (classAnnotationsOffset > 0) { reader.BaseStream.Position = classAnnotationsOffset; Annotations = Annotation.ReadAnnotationSetItem(reader); } } if (classDataOffset != 0) { reader.BaseStream.Position = classDataOffset; var staticFieldsCount = Leb128.ReadUleb(reader); var instanceFieldsCount = Leb128.ReadUleb(reader); var directMethodsCount = Leb128.ReadUleb(reader); var virtualMethodsCount = Leb128.ReadUleb(reader); StaticFields = ReadFields(staticFieldsCount, reader, fieldAnnotations); InstanceFields = ReadFields(instanceFieldsCount, reader, fieldAnnotations); DirectMethods = ReadMethods(directMethodsCount, reader, methodAnnotations, parameterAnnotations); VirtualMethods = ReadMethods(virtualMethodsCount, reader, methodAnnotations, parameterAnnotations); } else { StaticFields = new Field[0]; InstanceFields = new Field[0]; DirectMethods = new Method[0]; VirtualMethods = new Method[0]; } if (staticValuesOffset != 0) { reader.BaseStream.Position = staticValuesOffset; var size = Leb128.ReadUleb(reader); var values = new EncodedValue[size]; for (int i = 0; i < (int)size; i++) { values[i] = EncodedValue.parse(reader); } StaticFieldsValues = values; } else { StaticFieldsValues = new EncodedValue[0]; } }
/// <summary> /// Read a string at the specified offset in the DEX file. The layout of a String is: /// length: length of the decoded UTF16 string /// data: string encoded in MUTF8 ending in a \0 /// </summary> /// <returns> /// The string /// </returns> /// <param name='offset'> /// Offset of the string from the beginning of the file /// </param> /// <param name='reader'> /// stream reader to parse values from the Dex file /// </param> private string ReadString(uint offset, BinaryReader reader) { reader.BaseStream.Position = offset; // find out the length of the decoded string var stringLength = (int)Leb128.ReadUleb(reader); // strings are encoded in MUTF-8 format char[] chararr = new char[stringLength]; int c, char2, char3; int chararr_count = 0; while (chararr_count < stringLength) { c = reader.ReadByte(); switch (c >> 4) { /* 0xxxxxxx */ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: chararr[chararr_count++] = (char)c; break; /* 110x xxxx || 10xx xxxx */ case 12: case 13: char2 = reader.ReadByte(); if ((char2 & 0xC0) != 0x80) { throw new InvalidDataException("MUTF-8 parsing error. 2nd byte must be 10xxxxxx. Dex offset:" + (DexStream.Position - 2)); } chararr[chararr_count++] = (char)(((c & 0x1F) << 6) | (char2 & 0x3F)); break; /* 1110 xxxx || 10xx xxxx || 10xx xxxx */ case 14: char2 = reader.ReadByte(); char3 = reader.ReadByte(); if (((char2 & 0xC0) ^ (char3 & 0xC0)) != 0) { throw new InvalidDataException("MUTF-8 parsing error. Both bytes must be 10xxxxxx. Dex offset:" + (DexStream.Position - 3)); } chararr[chararr_count++] = (char)(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; default: throw new InvalidDataException("Invalid MUTF-8 encoding. Dex offset: " + (DexStream.Position - 1)); } } // The number of chars produced may be less than utflen return(new string(chararr, 0, chararr_count)); }
internal Method(uint id, Dex dex, BinaryReader reader, uint codeOffset) { Id = id; Dex = dex; ClassIndex = reader.ReadUInt16(); PrototypeIndex = reader.ReadUInt16(); NameIndex = reader.ReadUInt32(); Annotations = new Annotation[0]; ParameterAnnotations = new List <Annotation>(); // This method has no opcodes, must be abstract or native. // Or the method is being loaded directly from the methods list if (codeOffset != 0) { reader.BaseStream.Position = codeOffset; RegistersSize = reader.ReadUInt16(); ArgumentsSize = reader.ReadUInt16(); ReturnValuesSize = reader.ReadUInt16(); var numberOfTryItems = reader.ReadUInt16(); // Not parsing debug info /*var debugInfoOffset =*/ reader.ReadUInt32(); CodeLength = reader.ReadUInt32(); CodeOffset = reader.BaseStream.Position; // Skip the opcode block reader.BaseStream.Position += CodeLength * 2; // Skip the optional padding if ((numberOfTryItems != 0) && (CodeLength % 2 != 0)) { reader.BaseStream.Position += 2; } // Load the try blocks if (numberOfTryItems != 0) { TryCatchBlocks = new TryCatchBlock[numberOfTryItems]; var handlerOffsets = new long[numberOfTryItems]; // read Try for (int i = 0; i < numberOfTryItems; i++) { var tryCatch = new TryCatchBlock(CodeOffset); tryCatch.StartAddress = reader.ReadUInt32(); tryCatch.InstructionCount = reader.ReadUInt16(); TryCatchBlocks [i] = tryCatch; handlerOffsets[i] = reader.ReadUInt16(); } var encodedCatchHandlerListOffset = reader.BaseStream.Position; // Size of the list, could be used to confirm the DEX is properly // built. For this purpose will assume DEX files are always good Leb128.ReadUleb(reader); // read Catch blocks for (int i = 0; i < numberOfTryItems; i++) { //encoded_catch_handler if (handlerOffsets [i] > 0) { reader.BaseStream.Position = encodedCatchHandlerListOffset + handlerOffsets [i]; var handlersCount = Leb128.ReadLeb(reader); var handlers = new CatchHandler[handlersCount <= 0 ? Math.Abs(handlersCount) + 1 : handlersCount]; for (int j = 0; j < Math.Abs(handlersCount); j++) { var catchHandler = new CatchHandler(CodeOffset); catchHandler.TypeIndex = Leb128.ReadUleb(reader); catchHandler.Address = Leb128.ReadUleb(reader); handlers [j] = catchHandler; } // parse the catch all block if (handlersCount <= 0) { var catchHandler = new CatchHandler(CodeOffset); catchHandler.TypeIndex = 0; catchHandler.Address = Leb128.ReadUleb(reader); handlers [handlers.Length - 1] = catchHandler; } TryCatchBlocks [i].Handlers = handlers; } } } } }
public AnnotationElement(BinaryReader reader) { NameIdx = (uint)Leb128.ReadUleb(reader); Value = EncodedValue.parse(reader); }