private static void SerializeDynamicLocalInfo(IMethodBody methodBody, ArrayBuilder <MemoryStream> customDebugInfo) { if (!methodBody.HasDynamicLocalVariables) { return; //There are no dynamic locals } var dynamicLocals = ArrayBuilder <ILocalDefinition> .GetInstance(); foreach (ILocalDefinition local in methodBody.LocalVariables) { if (local.IsDynamic) { dynamicLocals.Add(local); } } int dynamicVariableCount = dynamicLocals.Count; foreach (var currentScope in methodBody.LocalScopes) { foreach (var localConstant in currentScope.Constants) { if (localConstant.IsDynamic) { dynamicLocals.Add(localConstant); } } } Debug.Assert(dynamicLocals.Any()); // There must be atleast one dynamic local if this point is reached const int blobSize = 200; //DynamicAttribute - 64, DynamicAttributeLength - 4, SlotIndex -4, IdentifierName - 128 MemoryStream customMetadata = new MemoryStream(); BinaryWriter cmw = new BinaryWriter(customMetadata, true); cmw.WriteByte(CDI.CdiVersion); cmw.WriteByte(CDI.CdiKindDynamicLocals); cmw.Align(4); // size = Version,Kind + size + cBuckets + (dynamicCount * sizeOf(Local Blob)) cmw.WriteUint(4 + 4 + 4 + (uint)dynamicLocals.Count * blobSize);//Size of the Dynamic Block cmw.WriteUint((uint)dynamicLocals.Count); int localIndex = 0; foreach (ILocalDefinition local in dynamicLocals) { if (local.Name.Length > 63)//Ignore and push empty information { cmw.WriteBytes(0, blobSize); continue; } var dynamicTransformFlags = local.DynamicTransformFlags; if (!dynamicTransformFlags.IsDefault && dynamicTransformFlags.Length <= 64) { byte[] flag = new byte[64]; for (int k = 0; k < dynamicTransformFlags.Length; k++) { if ((bool)dynamicTransformFlags[k].Value) { flag[k] = (byte)1; } } cmw.WriteBytes(flag); //Written Flag cmw.WriteUint((uint)dynamicTransformFlags.Length); //Written Length } else { cmw.WriteBytes(0, 68); //Empty flag array and size. } if (localIndex < dynamicVariableCount) { // Dynamic variable cmw.WriteUint((uint)local.SlotIndex); } else { // Dynamic constant cmw.WriteUint(0); } char[] localName = new char[64]; local.Name.CopyTo(0, localName, 0, local.Name.Length); cmw.WriteChars(localName); localIndex++; } dynamicLocals.Free(); customDebugInfo.Add(customMetadata); }
private void WriteDirectory(Directory directory, BinaryWriter writer, uint offset, uint level, uint sizeOfDirectoryTree, uint virtualAddressBase, BinaryWriter dataWriter) { writer.WriteUint(0); // Characteristics writer.WriteUint(0); // Timestamp writer.WriteUint(0); // Version writer.WriteUshort(directory.NumberOfNamedEntries); writer.WriteUshort(directory.NumberOfIdEntries); uint n = (uint)directory.Entries.Count; uint k = offset + 16 + n * 8; for (int i = 0; i < n; i++) { int id = int.MinValue; string name = null; uint nameOffset = dataWriter.BaseStream.Position + sizeOfDirectoryTree; uint directoryOffset = k; Directory subDir = directory.Entries[i] as Directory; if (subDir != null) { id = subDir.ID; name = subDir.Name; if (level == 0) { k += SizeOfDirectory(subDir); } else { k += 16 + 8 * (uint)subDir.Entries.Count; } } else { //EDMAURER write out an IMAGE_RESOURCE_DATA_ENTRY followed //immediately by the data that it refers to. This results //in a layout different than that produced by pulling the resources //from an OBJ. In that case all of the data bits of a resource are //contiguous in .rsrc$02. After processing these will end up at //the end of .rsrc following all of the directory //info and IMAGE_RESOURCE_DATA_ENTRYs IWin32Resource r = (IWin32Resource)directory.Entries[i]; id = level == 0 ? r.TypeId : level == 1 ? r.Id : (int)r.LanguageId; name = level == 0 ? r.TypeName : level == 1 ? r.Name : null; dataWriter.WriteUint(virtualAddressBase + sizeOfDirectoryTree + 16 + dataWriter.BaseStream.Position); byte[] data = new List<byte>(r.Data).ToArray(); dataWriter.WriteUint((uint)data.Length); dataWriter.WriteUint(r.CodePage); dataWriter.WriteUint(0); dataWriter.WriteBytes(data); while ((dataWriter.BaseStream.Length % 4) != 0) { dataWriter.WriteByte(0); } } if (id >= 0) { writer.WriteInt(id); } else { if (name == null) { name = string.Empty; } writer.WriteUint(nameOffset | 0x80000000); dataWriter.WriteUshort((ushort)name.Length); dataWriter.WriteChars(name.ToCharArray()); // REVIEW: what happens if the name contains chars that do not fit into a single utf8 code point? } if (subDir != null) { writer.WriteUint(directoryOffset | 0x80000000); } else { writer.WriteUint(nameOffset); } } k = offset + 16 + n * 8; for (int i = 0; i < n; i++) { Directory subDir = directory.Entries[i] as Directory; if (subDir != null) { this.WriteDirectory(subDir, writer, k, level + 1, sizeOfDirectoryTree, virtualAddressBase, dataWriter); if (level == 0) { k += SizeOfDirectory(subDir); } else { k += 16 + 8 * (uint)subDir.Entries.Count; } } } }
private static void SerializeDynamicLocalInfo(IMethodBody methodBody, ArrayBuilder<MemoryStream> customDebugInfo) { if (!methodBody.HasDynamicLocalVariables) { return; //There are no dynamic locals } var dynamicLocals = ArrayBuilder<ILocalDefinition>.GetInstance(); foreach (ILocalDefinition local in methodBody.LocalVariables) { if (local.IsDynamic) { dynamicLocals.Add(local); } } int dynamicVariableCount = dynamicLocals.Count; foreach (var currentScope in methodBody.LocalScopes) { foreach (var localConstant in currentScope.Constants) { if (localConstant.IsDynamic) { dynamicLocals.Add(localConstant); } } } Debug.Assert(dynamicLocals.Any()); // There must be atleast one dynamic local if this point is reached const int blobSize = 200;//DynamicAttribute - 64, DynamicAttributeLength - 4, SlotIndex -4, IdentifierName - 128 MemoryStream customMetadata = new MemoryStream(); BinaryWriter cmw = new BinaryWriter(customMetadata, true); cmw.WriteByte(CDI.CdiVersion); cmw.WriteByte(CDI.CdiKindDynamicLocals); cmw.Align(4); // size = Version,Kind + size + cBuckets + (dynamicCount * sizeOf(Local Blob)) cmw.WriteUint(4 + 4 + 4 + (uint)dynamicLocals.Count * blobSize);//Size of the Dynamic Block cmw.WriteUint((uint)dynamicLocals.Count); int localIndex = 0; foreach (ILocalDefinition local in dynamicLocals) { if (local.Name.Length > 63)//Ignore and push empty information { cmw.WriteBytes(0, blobSize); continue; } var dynamicTransformFlags = local.DynamicTransformFlags; if (!dynamicTransformFlags.IsDefault && dynamicTransformFlags.Length <= 64) { byte[] flag = new byte[64]; for (int k = 0; k < dynamicTransformFlags.Length; k++) { if ((bool)dynamicTransformFlags[k].Value) { flag[k] = (byte)1; } } cmw.WriteBytes(flag); //Written Flag cmw.WriteUint((uint)dynamicTransformFlags.Length); //Written Length } else { cmw.WriteBytes(0, 68); //Empty flag array and size. } if (localIndex < dynamicVariableCount) { // Dynamic variable cmw.WriteUint((uint)local.SlotIndex); } else { // Dynamic constant cmw.WriteUint(0); } char[] localName = new char[64]; local.Name.CopyTo(0, localName, 0, local.Name.Length); cmw.WriteChars(localName); localIndex++; } dynamicLocals.Free(); customDebugInfo.Add(customMetadata); }
public uint GetUserStringToken(string str) { uint index; if (!_userStringIndex.TryGetValue(str, out index)) { Debug.Assert(!_streamsAreComplete); index = _userStringWriter.BaseStream.Position + (uint)_userStringIndexStartOffset; _userStringIndex.Add(str, index); _userStringWriter.WriteCompressedUInt((uint)str.Length * 2 + 1); _userStringWriter.WriteChars(str.ToCharArray()); // Write out a trailing byte indicating if the string is really quite simple byte stringKind = 0; foreach (char ch in str) { if (ch >= 0x7F) { stringKind = 1; } else { switch ((int)ch) { case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7: case 0x8: case 0xE: case 0xF: case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F: case 0x27: case 0x2D: stringKind = 1; break; default: continue; } } break; } _userStringWriter.WriteByte(stringKind); } return(0x70000000 | index); }