/// <summary> /// Build IL header for new method. /// </summary> /// <param name="methodDef">Definition of new method.</param> /// <returns>Metadata token to local variables signature.</returns> private uint buildILHeader(MethodDefinition methodDef) { uint local_var = methodDef.Body.LocalVarToken.ToUInt32(); uint code_size = (uint)methodDef.Body.CodeSize; uint max_stack_size = (uint)methodDef.Body.MaxStackSize; bool tiny = methodDef.Body.IsTiny; if (!tiny) { uint header_flags = 0x3013; byte[] sig = metadata.NewImporter.GetSigantureSA(local_var); Signature signa = new Signature(sig); signa.Migrate(metadata); byte[] sig2 = signa.Compress(); metadata.OldEmitter.CorMetaDataEmit.GetTokenFromSig(sig2, (uint)sig2.Length, out local_var); buffer.AddRange(BitConverter.GetBytes((ushort)header_flags)); buffer.AddRange(BitConverter.GetBytes((ushort)max_stack_size)); //Util.uintToByteArray(max_stack_size,2)); buffer.AddRange(BitConverter.GetBytes(code_size)); //.uintToByteArray(code_size)); buffer.AddRange(BitConverter.GetBytes(local_var)); //.uintToByteArray(local_var)); return(local_var); } else { buffer.Add((byte)((code_size << 2) | 0x2)); return(0); } }
/// <summary> /// Emits scope debugging symbols based on <c>ISymUnmanagedScope</c> insatnce, representing /// scope from new assembly. /// </summary> /// <param name="smScope">Scope from new version of changed assembly.</param> /// <param name="placeholder">Placeholder translation for local variables.</param> public void EmitScope(ISymUnmanagedScope smScope, Dictionary <int, int> placeholder) { if (State != WriterState.Building) { throw new TranslatingException("ISym* interfaces were not initialized."); } uint scStartOffset = smScope.__GetStartOffset(); uint scEndOffset = smScope.__GetEndOffset(); mWriter.OpenScope(scStartOffset); uint localsCount = smScope.__GetLocalCount(); if (localsCount > 0) { uint read; ISymUnmanagedVariable[] variables = new ISymUnmanagedVariable[localsCount]; smScope.__GetLocals(localsCount, out read, variables); for (int i = 0; i < localsCount; i++) { byte[] signature = variables[i].GetSignature(); Signature sig = new Signature(signature); sig.Migrate(translator); signature = sig.Compress(); string name = variables[i].GetName(); uint addr1 = 0; //variables[i].GetAddressField1(); uint addr2 = 0; //variables[i].GetAddressField2(); uint addr3 = 0; //variables[i].GetAddressField3(); uint addrKind = variables[i].GetAddressKind(); //variables[i].GetAddressKind(); if ((variables[i].GetAttributes() & 1) != 1) { addr1 = variables[i].GetAddressField1(); addrKind = variables[i].GetAddressKind(); if (placeholder != null && placeholder.ContainsKey((int)addr1)) { addr1 = (uint)placeholder[(int)addr1]; } } uint varStartOffset = scStartOffset; uint varEndOffset = scEndOffset; uint attributes = variables[i].GetAttributes(); IntPtr pName = Marshal.StringToCoTaskMemUni(name); IntPtr pSig = Marshal.AllocCoTaskMem(signature.Length); Marshal.Copy(signature, 0, pSig, signature.Length); try{ mWriter.DefineLocalVariable(pName, attributes, (uint)signature.Length, pSig, addrKind, addr1, addr2, addr3, varStartOffset, varEndOffset); } finally { Marshal.FreeCoTaskMem(pSig); Marshal.FreeCoTaskMem(pName); } } } ISymUnmanagedScope[] subScopes = smScope.GetChildren(); foreach (ISymUnmanagedScope subScope in subScopes) { EmitScope(subScope, placeholder); } mWriter.CloseScope(scEndOffset); }
// +-----------------+ 0 // | delta header | ----->> size of the rest of IL in bytes // +-----------------+ 4 // | IL header | // +-----------------+ // | | // | IL code | // | | // +-----------------+ /// <summary> /// Builds header of changing method. /// </summary> /// <param name="newMethod">MethodDefinition of new version of changing method.</param> /// <param name="originMethod">MethoDefinition of original version of changing method.</param> /// <param name="tkMethod">Metadata token pointing to place of method in running version of metadata.</param> /// <param name="remapper">IL offset remapper, used to build local variable changes.</param> /// <param name="placeholder">Product of method, represents translation from old variable set to the new one.</param> /// <returns>Metadata token pointing to lolcalVars signature, if not present, 0 is given.</returns> private uint buildILHeader(MethodDefinition newMethod, MethodDefinition originMethod, SequencePointRemapper remapper, out Dictionary <int, int> placeholder) { uint local_var_old, token; uint local_var = newMethod.Body.LocalVarToken.ToUInt32(); uint code_size = (uint)newMethod.Body.CodeSize; uint max_stack_size = (uint)newMethod.Body.MaxStackSize; bool old_tiny = originMethod.Body.IsTiny; bool tiny = newMethod.Body.IsTiny; placeholder = null; if (old_tiny && !tiny) { // when new method is fat and the old tiny byte[] sig = metadata.NewImporter.GetSigantureSA(local_var); Signature signa = new Signature(sig); signa.Migrate(metadata); byte[] sig2 = signa.Compress(); metadata.OldEmitter.CorMetaDataEmit.GetTokenFromSig(sig2, (uint)sig2.Length, out token); tiny = false; } else if (!old_tiny && tiny) { // when new method is tiny and old fat local_var_old = originMethod.Body.LocalVarToken.ToUInt32(); local_var = local_var_old; max_stack_size = 8; tiny = false; } else if (!old_tiny && !tiny) { // both methods are fat Signature sigNew = new Signature(metadata.NewImporter.GetSigantureSA(local_var)); Signature sigOld = new Signature(metadata.OldImporter.GetSigantureSA(originMethod.Body.LocalVarToken.ToUInt32())); sigNew.Migrate(metadata); // Instead of unused old local variables use placeholders LocalVarDiff varDiff = new LocalVarDiff(Builder.Manager.ResourceManager.CurrentModule.SymReader, Builder.SymbolWriter.CorSymNewReader, remapper); byte[] sig = varDiff.makeSignature(sigOld, sigNew, out placeholder, originMethod.MetadataToken.ToUInt32(), newMethod.MetadataToken.ToUInt32(), metadata).Compress(); metadata.OldEmitter.CorMetaDataEmit.GetTokenFromSig(sig, (uint)sig.Length, out local_var); } //there is no need to change IL and MetaData when both methods are tiny if (!tiny) { uint header_flags = 0x3013; buffer.AddRange(BitConverter.GetBytes((ushort)header_flags)); //BitConverter.GetBytes((ushort)header_flags));//.uintToByteArray(header_flags,2)); buffer.AddRange(BitConverter.GetBytes((ushort)max_stack_size)); //Util.uintToByteArray(max_stack_size,2)); buffer.AddRange(BitConverter.GetBytes(code_size)); //.uintToByteArray(code_size)); buffer.AddRange(BitConverter.GetBytes(local_var)); //.uintToByteArray(local_var)); originMethod.Body.LocalVarToken = new MetadataToken(local_var); return(local_var); } else { buffer.Add((byte)((code_size << 2) | 0x2)); return(0); } }