private void ReadMethodBody(BinaryReader reader, MethodDefinition mdef, uint codeOffset) { reader.PreserveCurrentPosition(codeOffset, () => { ushort registersSize = reader.ReadUInt16(); ushort incomingArgsSize = reader.ReadUInt16(); ushort outgoingArgsSize = reader.ReadUInt16(); ushort triesSize = reader.ReadUInt16(); uint debugOffset = reader.ReadUInt32(); mdef.Body = new MethodBody(mdef, registersSize); mdef.Body.IncomingArguments = incomingArgsSize; mdef.Body.OutgoingArguments = outgoingArgsSize; var ireader = new InstructionReader(this, mdef); ireader.ReadFrom(reader); if ((triesSize != 0) && (ireader.Codes.Length % 2 != 0)) { reader.ReadUInt16(); // padding (4-byte alignment) } if (triesSize != 0) { ReadExceptionHandlers(reader, mdef, ireader, triesSize); } if (debugOffset != 0) { ReadDebugInfo(reader, mdef, ireader, debugOffset); } }); }
private void ReadExceptionHandlers(BinaryReader reader, MethodDefinition mdef, InstructionReader instructionReader, ushort triesSize) { var exceptionLookup = new Dictionary <uint, List <ExceptionHandler> >(); for (int i = 0; i < triesSize; i++) { uint startOffset = reader.ReadUInt32(); uint insCount = reader.ReadUInt16(); uint endOffset = startOffset + insCount - 1; uint handlerOffset = reader.ReadUInt16(); var ehandler = new ExceptionHandler(); mdef.Body.Exceptions.Add(ehandler); if (!exceptionLookup.ContainsKey(handlerOffset)) { exceptionLookup.Add(handlerOffset, new List <ExceptionHandler>()); } exceptionLookup[handlerOffset].Add(ehandler); ehandler.TryStart = instructionReader.Lookup[(int)startOffset]; // The last code unit covered (inclusive) is start_addr + insn_count - 1 ehandler.TryEnd = instructionReader.LookupLast[(int)endOffset]; } long baseOffset = reader.BaseStream.Position; uint catchHandlersSize = reader.ReadULEB128(); for (int i = 0; i < catchHandlersSize; i++) { long itemoffset = reader.BaseStream.Position - baseOffset; int catchTypes = reader.ReadSLEB128(); bool catchAllPresent = catchTypes <= 0; catchTypes = Math.Abs(catchTypes); for (int j = 0; j < catchTypes; j++) { uint typeIndex = reader.ReadULEB128(); uint offset = reader.ReadULEB128(); var @catch = new Catch(); @catch.Type = typeReferences[(int)typeIndex]; @catch.Instruction = instructionReader.Lookup[(int)offset]; // As catch handler can be used in several tries, let's clone the catch foreach (ExceptionHandler ehandler in exceptionLookup[(uint)itemoffset]) { ehandler.Catches.Add(@catch.Clone()); } } if (catchAllPresent) { uint offset = reader.ReadULEB128(); foreach (ExceptionHandler ehandler in exceptionLookup[(uint)itemoffset]) { ehandler.CatchAll = instructionReader.Lookup[(int)offset]; } } } }
private void ReadMethodBody(BinaryReader reader, MethodDefinition mdef, uint codeOffset) { reader.PreserveCurrentPosition(codeOffset, () => { ushort registersSize = reader.ReadUInt16(); ushort incomingArgsSize = reader.ReadUInt16(); ushort outgoingArgsSize = reader.ReadUInt16(); ushort triesSize = reader.ReadUInt16(); uint debugOffset = reader.ReadUInt32(); mdef.Body = new MethodBody(mdef, registersSize); mdef.Body.IncomingArguments = incomingArgsSize; mdef.Body.OutgoingArguments = outgoingArgsSize; var ireader = new InstructionReader(this, mdef); ireader.ReadFrom(reader); if ((triesSize != 0) && (ireader.Codes.Length%2 != 0)) reader.ReadUInt16(); // padding (4-byte alignment) if (triesSize != 0) ReadExceptionHandlers(reader, mdef, ireader, triesSize); if (debugOffset != 0) ReadDebugInfo(reader, mdef, ireader, debugOffset); }); }
private void ReadExceptionHandlers(BinaryReader reader, MethodDefinition mdef, InstructionReader instructionReader, ushort triesSize) { var exceptionLookup = new Dictionary<uint, List<ExceptionHandler>>(); for (int i = 0; i < triesSize; i++) { uint startOffset = reader.ReadUInt32(); uint insCount = reader.ReadUInt16(); uint endOffset = startOffset + insCount - 1; uint handlerOffset = reader.ReadUInt16(); var ehandler = new ExceptionHandler(); mdef.Body.Exceptions.Add(ehandler); if (!exceptionLookup.ContainsKey(handlerOffset)) { exceptionLookup.Add(handlerOffset, new List<ExceptionHandler>()); } exceptionLookup[handlerOffset].Add(ehandler); ehandler.TryStart = instructionReader.Lookup[(int) startOffset]; // The last code unit covered (inclusive) is start_addr + insn_count - 1 ehandler.TryEnd = instructionReader.LookupLast[(int) endOffset]; } long baseOffset = reader.BaseStream.Position; uint catchHandlersSize = reader.ReadULEB128(); for (int i = 0; i < catchHandlersSize; i++) { long itemoffset = reader.BaseStream.Position - baseOffset; int catchTypes = reader.ReadSLEB128(); bool catchAllPresent = catchTypes <= 0; catchTypes = Math.Abs(catchTypes); for (int j = 0; j < catchTypes; j++) { uint typeIndex = reader.ReadULEB128(); uint offset = reader.ReadULEB128(); var @catch = new Catch(); @catch.Type = typeReferences[(int) typeIndex]; @catch.Instruction = instructionReader.Lookup[(int) offset]; // As catch handler can be used in several tries, let's clone the catch foreach (ExceptionHandler ehandler in exceptionLookup[(uint) itemoffset]) ehandler.Catches.Add(@catch.Clone()); } if (catchAllPresent) { uint offset = reader.ReadULEB128(); foreach (ExceptionHandler ehandler in exceptionLookup[(uint) itemoffset]) ehandler.CatchAll = instructionReader.Lookup[(int) offset]; } } }
private void ReadDebugInfo(BinaryReader reader, MethodDefinition mdef, InstructionReader instructionReader, uint debugOffset) { reader.PreserveCurrentPosition(debugOffset, () => { var debugInfo = new DebugInfo(mdef.Body); mdef.Body.DebugInfo = debugInfo; uint lineStart = reader.ReadULEB128(); debugInfo.LineStart = lineStart; uint parametersSize = reader.ReadULEB128(); for (int i = 0; i < parametersSize; i++) { long index = reader.ReadULEB128p1(); string name = null; if (index != DexConsts.NoIndex && index >= 0) name = strings[(int) index]; debugInfo.Parameters.Add(name); } while (true) { var ins = new DebugInstruction((DebugOpCodes) reader.ReadByte()); debugInfo.DebugInstructions.Add(ins); uint registerIndex; uint addrDiff; long nameIndex; long typeIndex; long signatureIndex; int lineDiff; string name; switch (ins.OpCode) { case DebugOpCodes.AdvancePc: // uleb128 addr_diff addrDiff = reader.ReadULEB128(); ins.Operands.Add(addrDiff); break; case DebugOpCodes.AdvanceLine: // sleb128 line_diff lineDiff = reader.ReadSLEB128(); ins.Operands.Add(lineDiff); break; case DebugOpCodes.EndLocal: case DebugOpCodes.RestartLocal: // uleb128 register_num registerIndex = reader.ReadULEB128(); ins.Operands.Add(mdef.Body.Registers[(int) registerIndex]); break; case DebugOpCodes.SetFile: // uleb128p1 name_idx nameIndex = reader.ReadULEB128p1(); name = null; if (nameIndex != DexConsts.NoIndex && nameIndex >= 0) name = strings[(int) nameIndex]; ins.Operands.Add(name); break; case DebugOpCodes.StartLocalExtended: case DebugOpCodes.StartLocal: // StartLocalExtended : uleb128 register_num, uleb128p1 name_idx, uleb128p1 type_idx, uleb128p1 sig_idx // StartLocal : uleb128 register_num, uleb128p1 name_idx, uleb128p1 type_idx Boolean isExtended = ins.OpCode == DebugOpCodes. StartLocalExtended; registerIndex = reader.ReadULEB128(); ins.Operands.Add(mdef.Body.Registers[(int) registerIndex]); nameIndex = reader.ReadULEB128p1(); name = null; if (nameIndex != DexConsts.NoIndex && nameIndex >= 0) name = strings[(int) nameIndex]; ins.Operands.Add(name); typeIndex = reader.ReadULEB128p1(); TypeReference type = null; if (typeIndex != DexConsts.NoIndex && typeIndex >= 0) type = typeReferences[(int) typeIndex]; ins.Operands.Add(type); if (isExtended) { signatureIndex = reader.ReadULEB128p1(); string signature = null; if (signatureIndex != DexConsts.NoIndex && signatureIndex >= 0) signature = strings[(int) signatureIndex]; ins.Operands.Add(signature); } break; case DebugOpCodes.EndSequence: return; case DebugOpCodes.Special: // between 0x0a and 0xff (inclusive) case DebugOpCodes.SetPrologueEnd: case DebugOpCodes.SetEpilogueBegin: default: break; } } }); }
private void ReadDebugInfo(BinaryReader reader, MethodDefinition mdef, InstructionReader instructionReader, uint debugOffset) { reader.PreserveCurrentPosition(debugOffset, () => { var debugInfo = new DebugInfo(mdef.Body); mdef.Body.DebugInfo = debugInfo; uint lineStart = reader.ReadULEB128(); debugInfo.LineStart = lineStart; uint parametersSize = reader.ReadULEB128(); for (int i = 0; i < parametersSize; i++) { long index = reader.ReadULEB128p1(); string name = null; if (index != DexConsts.NoIndex && index >= 0) { name = strings[(int)index]; } debugInfo.Parameters.Add(name); } while (true) { var ins = new DebugInstruction((DebugOpCodes)reader.ReadByte()); debugInfo.DebugInstructions.Add(ins); uint registerIndex; uint addrDiff; long nameIndex; long typeIndex; long signatureIndex; int lineDiff; string name; switch (ins.OpCode) { case DebugOpCodes.AdvancePc: // uleb128 addr_diff addrDiff = reader.ReadULEB128(); ins.Operands.Add(addrDiff); break; case DebugOpCodes.AdvanceLine: // sleb128 line_diff lineDiff = reader.ReadSLEB128(); ins.Operands.Add(lineDiff); break; case DebugOpCodes.EndLocal: case DebugOpCodes.RestartLocal: // uleb128 register_num registerIndex = reader.ReadULEB128(); ins.Operands.Add(mdef.Body.Registers[(int)registerIndex]); break; case DebugOpCodes.SetFile: // uleb128p1 name_idx nameIndex = reader.ReadULEB128p1(); name = null; if (nameIndex != DexConsts.NoIndex && nameIndex >= 0) { name = strings[(int)nameIndex]; } ins.Operands.Add(name); break; case DebugOpCodes.StartLocalExtended: case DebugOpCodes.StartLocal: // StartLocalExtended : uleb128 register_num, uleb128p1 name_idx, uleb128p1 type_idx, uleb128p1 sig_idx // StartLocal : uleb128 register_num, uleb128p1 name_idx, uleb128p1 type_idx Boolean isExtended = ins.OpCode == DebugOpCodes. StartLocalExtended; registerIndex = reader.ReadULEB128(); ins.Operands.Add(mdef.Body.Registers[(int)registerIndex]); nameIndex = reader.ReadULEB128p1(); name = null; if (nameIndex != DexConsts.NoIndex && nameIndex >= 0) { name = strings[(int)nameIndex]; } ins.Operands.Add(name); typeIndex = reader.ReadULEB128p1(); TypeReference type = null; if (typeIndex != DexConsts.NoIndex && typeIndex >= 0) { type = typeReferences[(int)typeIndex]; } ins.Operands.Add(type); if (isExtended) { signatureIndex = reader.ReadULEB128p1(); string signature = null; if (signatureIndex != DexConsts.NoIndex && signatureIndex >= 0) { signature = strings[(int)signatureIndex]; } ins.Operands.Add(signature); } break; case DebugOpCodes.EndSequence: return; case DebugOpCodes.Special: // between 0x0a and 0xff (inclusive) case DebugOpCodes.SetPrologueEnd: case DebugOpCodes.SetEpilogueBegin: default: break; } } }); }