public InstructionWriter(DexWriter dexWriter, MethodDefinition method) { DexWriter = dexWriter; MethodDefinition = method; LookupLast = new Dictionary<Instruction, int>(); _ip = 0; _extraOffset = 0; }
public InstructionReader(Dex dex, MethodDefinition mdef) { Dex = dex; MethodDefinition = mdef; Lookup = new Dictionary<int, Instruction>(); LookupLast = new Dictionary<int, Instruction>(); LazyInstructionsSetters = new List<Action>(); _ip = 0; }
public MethodBody(MethodDefinition method, int registersSize) { Owner = method; Registers = new List<Register>(); for (var i = 0; i < registersSize; i++) { Registers.Add(new Register(i)); } Instructions = new List<Instruction>(); Exceptions = new List<ExceptionHandler>(); }
public bool Equals(MethodDefinition other) { // Should be enough (ownership) return base.Equals(other); }
private void ReadMethodBody(BinaryReader reader, MethodDefinition mdef, uint codeOffset) { reader.PreserveCurrentPosition(codeOffset, () => { var registersSize = reader.ReadUInt16(); var incomingArgsSize = reader.ReadUInt16(); var outgoingArgsSize = reader.ReadUInt16(); var triesSize = reader.ReadUInt16(); var debugOffset = reader.ReadUInt32(); mdef.Body = new MethodBody(mdef, registersSize) { IncomingArguments = incomingArgsSize, OutgoingArguments = outgoingArgsSize }; var ireader = new InstructionReader(Dex, 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, debugOffset); }); }
private void ReadExceptionHandlers(BinaryReader reader, MethodDefinition mdef, InstructionReader instructionReader, ushort triesSize) { var exceptionLookup = new Dictionary<uint, List<ExceptionHandler>>(); for (var i = 0; i < triesSize; i++) { var startOffset = reader.ReadUInt32(); var insCount = reader.ReadUInt16(); var 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]; } var baseOffset = reader.BaseStream.Position; var catchHandlersSize = reader.ReadULEB128(); for (var i = 0; i < catchHandlersSize; i++) { var itemoffset = reader.BaseStream.Position - baseOffset; var catchTypes = reader.ReadSLEB128(); var catchAllPresent = catchTypes <= 0; catchTypes = Math.Abs(catchTypes); for (var j = 0; j < catchTypes; j++) { var typeIndex = reader.ReadULEB128(); var offset = reader.ReadULEB128(); var @catch = new Catch { Type = Dex.TypeReferences[(int) typeIndex], Instruction = instructionReader.Lookup[(int) offset] }; // As catch handler can be used in several tries, let's clone the catch foreach (var ehandler in exceptionLookup[(uint)itemoffset]) ehandler.Catches.Add(@catch.Clone()); } if (!catchAllPresent) continue; var caOffset = reader.ReadULEB128(); foreach (var ehandler in exceptionLookup[(uint)itemoffset]) ehandler.CatchAll = instructionReader.Lookup[(int)caOffset]; } }
private void ReadDebugInfo(BinaryReader reader, MethodDefinition mdef, uint debugOffset) { reader.PreserveCurrentPosition(debugOffset, () => { var debugInfo = new DebugInfo(mdef.Body); mdef.Body.DebugInfo = debugInfo; var lineStart = reader.ReadULEB128(); debugInfo.LineStart = lineStart; var parametersSize = reader.ReadULEB128(); for (var i = 0; i < parametersSize; i++) { var index = reader.ReadULEB128P1(); string name = null; if (index != DexConsts.NoIndex && index >= 0) name = Dex.Strings[(int)index]; debugInfo.Parameters.Add(name); } while (true) { var ins = new DebugInstruction {OpCode = (DebugOpCodes) reader.ReadByte()}; debugInfo.DebugInstructions.Add(ins); uint registerIndex; long nameIndex; string name; switch (ins.OpCode) { case DebugOpCodes.AdvancePc: // uleb128 addr_diff var addrDiff = reader.ReadULEB128(); ins.Operands.Add(addrDiff); break; case DebugOpCodes.AdvanceLine: // sleb128 line_diff var 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 = Dex.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 var 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 = Dex.Strings[(int)nameIndex]; ins.Operands.Add(name); var typeIndex = reader.ReadULEB128P1(); TypeReference type = null; if (typeIndex != DexConsts.NoIndex && typeIndex >= 0) type = Dex.TypeReferences[(int)typeIndex]; ins.Operands.Add(type); if (isExtended) { var signatureIndex = reader.ReadULEB128P1(); string signature = null; if (signatureIndex != DexConsts.NoIndex && signatureIndex >= 0) signature = Dex.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 PrefetchMethodDefinitions(BinaryReader reader, uint methodcount) { var methodIndex = 0; for (var i = 0; i < methodcount; i++) { if (i == 0) methodIndex = (int)reader.ReadULEB128(); else methodIndex += (int)reader.ReadULEB128(); reader.ReadULEB128(); reader.ReadULEB128(); var mdef = new MethodDefinition(Dex.MethodReferences[methodIndex]); Dex.MethodReferences[methodIndex] = mdef; } }
// ReSharper restore ValueParameterNotUsed public bool Equals(MethodDefinition other) { // Should be enough (ownership) return(base.Equals(other)); }