Пример #1
0
		internal void Freeze(MetadataWriter mw)
		{
			if (frozen)
				throw new InvalidOperationException();
			frozen = true;
			unalignedlength = GetLength(mw);
		}
Пример #2
0
		internal void Write(MetadataWriter mw, uint rva)
		{
			foreach (int offset in linkOffsets)
			{
				bb.Position = offset;
				bb.Write(bb.GetInt32AtCurrentPosition() + (int)rva);
			}
			mw.Write(bb);
		}
Пример #3
0
		internal void Write(MetadataWriter mw)
		{
			int pos = mw.Position;
			WriteImpl(mw);
			Debug.Assert(mw.Position == pos + unalignedlength);
			int align = Length - unalignedlength;
			for (int i = 0; i < align; i++)
			{
				mw.Write((byte)0);
			}
		}
Пример #4
0
		internal void WriteTypeDefRecord(MetadataWriter mw, ref int fieldList, ref int methodList)
		{
			mw.Write((int)attribs);
			mw.WriteStringIndex(typeName);
			mw.WriteStringIndex(typeNameSpace);
			mw.WriteTypeDefOrRef(extends);
			mw.WriteField(fieldList);
			mw.WriteMethodDef(methodList);
			methodList += methods.Count;
			fieldList += fields.Count;
		}
Пример #5
0
		internal void WriteMethodDefRecord(int baseRVA, MetadataWriter mw, ref int paramList)
		{
			if (rva != -1)
			{
				mw.Write(rva + baseRVA);
			}
			else
			{
				mw.Write(0);
			}
			mw.Write((short)implFlags);
			mw.Write((short)attributes);
			mw.WriteStringIndex(nameIndex);
			mw.WriteBlobIndex(signature);
			mw.WriteParam(paramList);
			if (parameters != null)
			{
				paramList += parameters.Count;
			}
		}
Пример #6
0
		protected override void WriteImpl(MetadataWriter mw)
		{
			mw.Write(buf);
		}
Пример #7
0
		protected override void WriteImpl(MetadataWriter mw)
		{
			foreach (Guid guid in list)
			{
				mw.Write(guid.ToByteArray());
			}
		}
Пример #8
0
		protected override void WriteImpl(MetadataWriter mw)
		{
			foreach (string str in list)
			{
				mw.Write(System.Text.Encoding.UTF8.GetBytes(str));
				mw.Write((byte)0);
			}
		}
Пример #9
0
		private static void WriteModuleImpl(StrongNameKeyPair keyPair, byte[] publicKey, ModuleBuilder moduleBuilder,
			PEFileKinds fileKind, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine,
			ResourceSection resources, int entryPointToken, Stream stream)
		{
			moduleBuilder.ApplyUnmanagedExports(imageFileMachine);
			moduleBuilder.FixupMethodBodyTokens();

			moduleBuilder.ModuleTable.Add(0, moduleBuilder.Strings.Add(moduleBuilder.moduleName), moduleBuilder.Guids.Add(moduleBuilder.ModuleVersionId), 0, 0);

			if (moduleBuilder.UserStrings.IsEmpty)
			{
				// for compat with Ref.Emit, if there aren't any user strings, we add one
				moduleBuilder.UserStrings.Add(" ");
			}

			if (resources != null)
			{
				resources.Finish();
			}

			PEWriter writer = new PEWriter(stream);
			writer.Headers.OptionalHeader.FileAlignment = (uint)moduleBuilder.__FileAlignment;
			switch (imageFileMachine)
			{
				case ImageFileMachine.I386:
					writer.Headers.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386;
					writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_32BIT_MACHINE;
					writer.Headers.OptionalHeader.SizeOfStackReserve = moduleBuilder.GetStackReserve(0x100000);
					break;
				case ImageFileMachine.ARM:
					writer.Headers.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_ARM;
					writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_32BIT_MACHINE;
					writer.Headers.OptionalHeader.SizeOfStackReserve = moduleBuilder.GetStackReserve(0x100000);
					break;
				case ImageFileMachine.AMD64:
					writer.Headers.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64;
					writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_LARGE_ADDRESS_AWARE;
					writer.Headers.FileHeader.SizeOfOptionalHeader = 0xF0;
					writer.Headers.OptionalHeader.Magic = IMAGE_OPTIONAL_HEADER.IMAGE_NT_OPTIONAL_HDR64_MAGIC;
					writer.Headers.OptionalHeader.SizeOfStackReserve = moduleBuilder.GetStackReserve(0x400000);
					writer.Headers.OptionalHeader.SizeOfStackCommit = 0x4000;
					writer.Headers.OptionalHeader.SizeOfHeapCommit = 0x2000;
					break;
				case ImageFileMachine.IA64:
					writer.Headers.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64;
					writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_LARGE_ADDRESS_AWARE;
					writer.Headers.FileHeader.SizeOfOptionalHeader = 0xF0;
					writer.Headers.OptionalHeader.Magic = IMAGE_OPTIONAL_HEADER.IMAGE_NT_OPTIONAL_HDR64_MAGIC;
					writer.Headers.OptionalHeader.SizeOfStackReserve = moduleBuilder.GetStackReserve(0x400000);
					writer.Headers.OptionalHeader.SizeOfStackCommit = 0x4000;
					writer.Headers.OptionalHeader.SizeOfHeapCommit = 0x2000;
					break;
				default:
					throw new ArgumentOutOfRangeException("imageFileMachine");
			}
			if (fileKind == PEFileKinds.Dll)
			{
				writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_DLL;
			}

			switch (fileKind)
			{
				case PEFileKinds.WindowApplication:
					writer.Headers.OptionalHeader.Subsystem = IMAGE_OPTIONAL_HEADER.IMAGE_SUBSYSTEM_WINDOWS_GUI;
					break;
				default:
					writer.Headers.OptionalHeader.Subsystem = IMAGE_OPTIONAL_HEADER.IMAGE_SUBSYSTEM_WINDOWS_CUI;
					break;
			}
			writer.Headers.OptionalHeader.DllCharacteristics = (ushort)moduleBuilder.__DllCharacteristics;

			CliHeader cliHeader = new CliHeader();
			cliHeader.Cb = 0x48;
			cliHeader.MajorRuntimeVersion = 2;
			cliHeader.MinorRuntimeVersion = moduleBuilder.MDStreamVersion < 0x20000 ? (ushort)0 : (ushort)5;
			if ((portableExecutableKind & PortableExecutableKinds.ILOnly) != 0)
			{
				cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_ILONLY;
			}
			if ((portableExecutableKind & PortableExecutableKinds.Required32Bit) != 0)
			{
				cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_32BITREQUIRED;
			}
			if ((portableExecutableKind & PortableExecutableKinds.Preferred32Bit) != 0)
			{
				cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_32BITREQUIRED | CliHeader.COMIMAGE_FLAGS_32BITPREFERRED;
			}
			if (keyPair != null)
			{
				cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_STRONGNAMESIGNED;
			}
			if (moduleBuilder.IsPseudoToken(entryPointToken))
			{
				entryPointToken = moduleBuilder.ResolvePseudoToken(entryPointToken);
			}
			cliHeader.EntryPointToken = (uint)entryPointToken;

			moduleBuilder.Strings.Freeze();
			moduleBuilder.UserStrings.Freeze();
			moduleBuilder.Guids.Freeze();
			moduleBuilder.Blobs.Freeze();
			MetadataWriter mw = new MetadataWriter(moduleBuilder, stream);
			moduleBuilder.Tables.Freeze(mw);
			TextSection code = new TextSection(writer, cliHeader, moduleBuilder, ComputeStrongNameSignatureLength(publicKey));

			// Export Directory
			if (code.ExportDirectoryLength != 0)
			{
				writer.Headers.OptionalHeader.DataDirectory[0].VirtualAddress = code.ExportDirectoryRVA;
				writer.Headers.OptionalHeader.DataDirectory[0].Size = code.ExportDirectoryLength;
			}

			// Import Directory
			if (code.ImportDirectoryLength != 0)
			{
				writer.Headers.OptionalHeader.DataDirectory[1].VirtualAddress = code.ImportDirectoryRVA;
				writer.Headers.OptionalHeader.DataDirectory[1].Size = code.ImportDirectoryLength;
			}

			// Import Address Table Directory
			if (code.ImportAddressTableLength != 0)
			{
				writer.Headers.OptionalHeader.DataDirectory[12].VirtualAddress = code.ImportAddressTableRVA;
				writer.Headers.OptionalHeader.DataDirectory[12].Size = code.ImportAddressTableLength;
			}

			// COM Descriptor Directory
			writer.Headers.OptionalHeader.DataDirectory[14].VirtualAddress = code.ComDescriptorRVA;
			writer.Headers.OptionalHeader.DataDirectory[14].Size = code.ComDescriptorLength;

			// Debug Directory
			if (code.DebugDirectoryLength != 0)
			{
				writer.Headers.OptionalHeader.DataDirectory[6].VirtualAddress = code.DebugDirectoryRVA;
				writer.Headers.OptionalHeader.DataDirectory[6].Size = code.DebugDirectoryLength;
			}

			// we need to start by computing the number of sections, because code.PointerToRawData depends on that
			writer.Headers.FileHeader.NumberOfSections = 1;

			if (moduleBuilder.initializedData.Length != 0)
			{
				// .sdata
				writer.Headers.FileHeader.NumberOfSections++;
			}

			if (resources != null)
			{
				// .rsrc
				writer.Headers.FileHeader.NumberOfSections++;
			}

			if (imageFileMachine != ImageFileMachine.ARM)
			{
				// .reloc
				writer.Headers.FileHeader.NumberOfSections++;
			}

			SectionHeader text = new SectionHeader();
			text.Name = ".text";
			text.VirtualAddress = code.BaseRVA;
			text.VirtualSize = (uint)code.Length;
			text.PointerToRawData = code.PointerToRawData;
			text.SizeOfRawData = writer.ToFileAlignment((uint)code.Length);
			text.Characteristics = SectionHeader.IMAGE_SCN_CNT_CODE | SectionHeader.IMAGE_SCN_MEM_EXECUTE | SectionHeader.IMAGE_SCN_MEM_READ;

			SectionHeader sdata = new SectionHeader();
			sdata.Name = ".sdata";
			sdata.VirtualAddress = text.VirtualAddress + writer.ToSectionAlignment(text.VirtualSize);
			sdata.VirtualSize = (uint)moduleBuilder.initializedData.Length;
			sdata.PointerToRawData = text.PointerToRawData + text.SizeOfRawData;
			sdata.SizeOfRawData = writer.ToFileAlignment((uint)moduleBuilder.initializedData.Length);
			sdata.Characteristics = SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA | SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_MEM_WRITE;

			SectionHeader rsrc = new SectionHeader();
			rsrc.Name = ".rsrc";
			rsrc.VirtualAddress = sdata.VirtualAddress + writer.ToSectionAlignment(sdata.VirtualSize);
			rsrc.PointerToRawData = sdata.PointerToRawData + sdata.SizeOfRawData;
			rsrc.VirtualSize = resources == null ? 0 : (uint)resources.Length;
			rsrc.SizeOfRawData = writer.ToFileAlignment(rsrc.VirtualSize);
			rsrc.Characteristics = SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA;

			if (rsrc.SizeOfRawData != 0)
			{
				// Resource Directory
				writer.Headers.OptionalHeader.DataDirectory[2].VirtualAddress = rsrc.VirtualAddress;
				writer.Headers.OptionalHeader.DataDirectory[2].Size = rsrc.VirtualSize;
			}

			SectionHeader reloc = new SectionHeader();
			reloc.Name = ".reloc";
			reloc.VirtualAddress = rsrc.VirtualAddress + writer.ToSectionAlignment(rsrc.VirtualSize);
			if (imageFileMachine != ImageFileMachine.ARM)
			{
				reloc.VirtualSize = ((uint)moduleBuilder.unmanagedExports.Count + 1) * 12;
			}
			reloc.PointerToRawData = rsrc.PointerToRawData + rsrc.SizeOfRawData;
			reloc.SizeOfRawData = writer.ToFileAlignment(reloc.VirtualSize);
			reloc.Characteristics = SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA | SectionHeader.IMAGE_SCN_MEM_DISCARDABLE;

			if (reloc.SizeOfRawData != 0)
			{
				// Base Relocation Directory
				writer.Headers.OptionalHeader.DataDirectory[5].VirtualAddress = reloc.VirtualAddress;
				writer.Headers.OptionalHeader.DataDirectory[5].Size = reloc.VirtualSize;
			}

			writer.Headers.OptionalHeader.SizeOfCode = text.SizeOfRawData;
			writer.Headers.OptionalHeader.SizeOfInitializedData = sdata.SizeOfRawData + rsrc.SizeOfRawData + reloc.SizeOfRawData;
			writer.Headers.OptionalHeader.SizeOfUninitializedData = 0;
			writer.Headers.OptionalHeader.SizeOfImage = reloc.VirtualAddress + writer.ToSectionAlignment(reloc.VirtualSize);
			writer.Headers.OptionalHeader.SizeOfHeaders = text.PointerToRawData;
			writer.Headers.OptionalHeader.BaseOfCode = code.BaseRVA;
			writer.Headers.OptionalHeader.BaseOfData = sdata.VirtualAddress;
			writer.Headers.OptionalHeader.ImageBase = (ulong)moduleBuilder.__ImageBase;

			if (imageFileMachine == ImageFileMachine.IA64)
			{
				// apparently for IA64 AddressOfEntryPoint points to the address of the entry point
				// (i.e. there is an additional layer of indirection), so we add the offset to the pointer
				writer.Headers.OptionalHeader.AddressOfEntryPoint = code.StartupStubRVA + 0x20;
			}
			else if (imageFileMachine != ImageFileMachine.ARM)
			{
				writer.Headers.OptionalHeader.AddressOfEntryPoint = code.StartupStubRVA;
			}

			writer.WritePEHeaders();
			writer.WriteSectionHeader(text);
			if (sdata.SizeOfRawData != 0)
			{
				writer.WriteSectionHeader(sdata);
			}
			if (rsrc.SizeOfRawData != 0)
			{
				writer.WriteSectionHeader(rsrc);
			}
			if (reloc.SizeOfRawData != 0)
			{
				writer.WriteSectionHeader(reloc);
			}

			stream.Seek(text.PointerToRawData, SeekOrigin.Begin);
			code.Write(mw, sdata.VirtualAddress);

			if (sdata.SizeOfRawData != 0)
			{
				stream.Seek(sdata.PointerToRawData, SeekOrigin.Begin);
				mw.Write(moduleBuilder.initializedData);
			}

			if (rsrc.SizeOfRawData != 0)
			{
				stream.Seek(rsrc.PointerToRawData, SeekOrigin.Begin);
				resources.Write(mw, rsrc.VirtualAddress);
			}

			if (reloc.SizeOfRawData != 0)
			{
				stream.Seek(reloc.PointerToRawData, SeekOrigin.Begin);
				code.WriteRelocations(mw);
			}

			// file alignment
			stream.SetLength(reloc.PointerToRawData + reloc.SizeOfRawData);

			// do the strong naming
			if (keyPair != null)
			{
				StrongName(stream, keyPair, writer.HeaderSize, text.PointerToRawData, code.StrongNameSignatureRVA - text.VirtualAddress + text.PointerToRawData, code.StrongNameSignatureLength);
			}

			if (moduleBuilder.symbolWriter != null)
			{
				moduleBuilder.WriteSymbolTokenMap();
				moduleBuilder.symbolWriter.Close();
			}
		}
Пример #10
0
			internal void Write(MetadataWriter mw, uint sdataRVA)
			{
				// sort the exports by ordinal
				text.moduleBuilder.unmanagedExports.Sort(CompareUnmanagedExportOrdinals);

				// Now write the Export Address Table
				text.AssertRVA(mw, exportAddressTableRVA);
				for (int i = 0, pos = 0; i < entries; i++)
				{
					if (text.moduleBuilder.unmanagedExports[pos].ordinal == i + ordinalBase)
					{
						mw.Write(stubsRVA + (uint)pos * stubLength);
						pos++;
					}
					else
					{
						mw.Write(0);
					}
				}

				// sort the exports by name
				text.moduleBuilder.unmanagedExports.Sort(CompareUnmanagedExportNames);

				// Now write the Export Name Pointer Table
				text.AssertRVA(mw, exportNamePointerTableRVA);
				uint nameOffset = (uint)text.moduleBuilder.fileName.Length + 1;
				foreach (UnmanagedExport exp in text.moduleBuilder.unmanagedExports)
				{
					if (exp.name != null)
					{
						mw.Write(namesRVA + nameOffset);
						nameOffset += (uint)exp.name.Length + 1;
					}
				}

				// Now write the Export Ordinal Table
				text.AssertRVA(mw, exportOrdinalTableRVA);
				foreach (UnmanagedExport exp in text.moduleBuilder.unmanagedExports)
				{
					if (exp.name != null)
					{
						mw.Write((ushort)(exp.ordinal - ordinalBase));
					}
				}

				// Now write the actual names
				text.AssertRVA(mw, namesRVA);
				mw.Write(Encoding.ASCII.GetBytes(text.moduleBuilder.fileName));
				mw.Write((byte)0);
				foreach (UnmanagedExport exp in text.moduleBuilder.unmanagedExports)
				{
					if (exp.name != null)
					{
						mw.Write(Encoding.ASCII.GetBytes(exp.name));
						mw.Write((byte)0);
					}
				}
				text.AssertRVA(mw, namesRVA + namesLength);

				// alignment padding
				for (int i = (int)(stubsRVA - (namesRVA + namesLength)); i > 0; i--)
				{
					mw.Write((byte)0);
				}

				// sort the exports by ordinal
				text.moduleBuilder.unmanagedExports.Sort(CompareUnmanagedExportOrdinals);

				// Now write the stubs
				text.AssertRVA(mw, stubsRVA);

				for (int i = 0, pos = 0; i < entries; i++)
				{
					if (text.moduleBuilder.unmanagedExports[pos].ordinal == i + ordinalBase)
					{
						switch (text.peWriter.Headers.FileHeader.Machine)
						{
							case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386:
								mw.Write((byte)0xFF);
								mw.Write((byte)0x25);
								mw.Write((uint)text.peWriter.Headers.OptionalHeader.ImageBase + text.moduleBuilder.unmanagedExports[pos].rva.initializedDataOffset + sdataRVA);
								mw.Write((short)0);	// alignment
								break;
							case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64:
								mw.Write((byte)0x48);
								mw.Write((byte)0xA1);
								mw.Write(text.peWriter.Headers.OptionalHeader.ImageBase + text.moduleBuilder.unmanagedExports[pos].rva.initializedDataOffset + sdataRVA);
								mw.Write((byte)0xFF);
								mw.Write((byte)0xE0);
								mw.Write(0); // alignment
								break;
							default:
								throw new NotImplementedException();
						}
						pos++;
					}
				}
			}
Пример #11
0
		private void WriteDebugDirectory(MetadataWriter mw)
		{
			if (DebugDirectoryLength != 0)
			{
				IMAGE_DEBUG_DIRECTORY idd = new IMAGE_DEBUG_DIRECTORY();
				idd.Characteristics = 0;
				idd.TimeDateStamp = peWriter.Headers.FileHeader.TimeDateStamp;
				byte[] buf = SymbolSupport.GetDebugInfo(moduleBuilder.symbolWriter, ref idd);
				idd.PointerToRawData = (DebugDirectoryRVA - BaseRVA) + DebugDirectoryLength + PointerToRawData;
				mw.Write(idd.Characteristics);
				mw.Write(idd.TimeDateStamp);
				mw.Write(idd.MajorVersion);
				mw.Write(idd.MinorVersion);
				mw.Write(idd.Type);
				mw.Write(idd.SizeOfData);
				mw.Write(idd.AddressOfRawData);
				mw.Write(idd.PointerToRawData);
				mw.Write(buf);
			}
		}
Пример #12
0
		private void WriteVTableFixups(MetadataWriter mw, uint sdataRVA)
		{
			foreach (ModuleBuilder.VTableFixups fixups in moduleBuilder.vtablefixups)
			{
				mw.Write(fixups.initializedDataOffset + sdataRVA);
				mw.Write(fixups.count);
				mw.Write(fixups.type);
			}
		}
Пример #13
0
		private void AssertRVA(MetadataWriter mw, uint rva)
		{
			Debug.Assert(mw.Position - PointerToRawData + BaseRVA == rva);
		}
Пример #14
0
 private void AssertRVA(MetadataWriter mw, uint rva)
 {
     Debug.Assert(mw.Position - PointerToRawData + BaseRVA == rva);
 }
Пример #15
0
		internal void WriteParamRecords(MetadataWriter mw)
		{
			foreach (MethodBuilder mb in methods)
			{
				mb.WriteParamRecords(mw);
			}
		}
Пример #16
0
        internal void Write(MetadataWriter mw, uint sdataRVA, out uint guidHeapOffset)
        {
            // Now that we're ready to start writing, we need to do some fix ups
            moduleBuilder.TypeRef.Fixup(moduleBuilder);
            moduleBuilder.MethodDef.Fixup(this);
            moduleBuilder.MethodImpl.Fixup(moduleBuilder);
            moduleBuilder.MethodSemantics.Fixup(moduleBuilder);
            moduleBuilder.InterfaceImpl.Fixup();
            moduleBuilder.ResolveInterfaceImplPseudoTokens();
            moduleBuilder.MemberRef.Fixup(moduleBuilder);
            moduleBuilder.Constant.Fixup(moduleBuilder);
            moduleBuilder.FieldMarshal.Fixup(moduleBuilder);
            moduleBuilder.DeclSecurity.Fixup(moduleBuilder);
            moduleBuilder.GenericParam.Fixup(moduleBuilder);
            moduleBuilder.CustomAttribute.Fixup(moduleBuilder);
            moduleBuilder.FieldLayout.Fixup(moduleBuilder);
            moduleBuilder.FieldRVA.Fixup(moduleBuilder, (int)sdataRVA, (int)this.MethodBodiesRVA);
            moduleBuilder.ImplMap.Fixup(moduleBuilder);
            moduleBuilder.ExportedType.Fixup(moduleBuilder);
            moduleBuilder.ManifestResource.Fixup(moduleBuilder);
            moduleBuilder.MethodSpec.Fixup(moduleBuilder);
            moduleBuilder.GenericParamConstraint.Fixup(moduleBuilder);

            // Import Address Table
            AssertRVA(mw, ImportAddressTableRVA);
            if (ImportAddressTableLength != 0)
            {
                WriteRVA(mw, ImportHintNameTableRVA);
                WriteRVA(mw, 0);
            }

            // CLI Header
            AssertRVA(mw, ComDescriptorRVA);
            cliHeader.MetaData.VirtualAddress = MetadataRVA;
            cliHeader.MetaData.Size           = MetadataLength;
            if (ResourcesLength != 0)
            {
                cliHeader.Resources.VirtualAddress = ResourcesRVA;
                cliHeader.Resources.Size           = ResourcesLength;
            }
            if (StrongNameSignatureLength != 0)
            {
                cliHeader.StrongNameSignature.VirtualAddress = StrongNameSignatureRVA;
                cliHeader.StrongNameSignature.Size           = StrongNameSignatureLength;
            }
            if (VTableFixupsLength != 0)
            {
                cliHeader.VTableFixups.VirtualAddress = VTableFixupsRVA;
                cliHeader.VTableFixups.Size           = VTableFixupsLength;
            }
            cliHeader.Write(mw);

            // alignment padding
            for (int i = (int)(MethodBodiesRVA - (ComDescriptorRVA + ComDescriptorLength)); i > 0; i--)
            {
                mw.Write((byte)0);
            }

            // Method Bodies
            mw.Write(moduleBuilder.methodBodies);

            // alignment padding
            for (int i = (int)(ResourcesRVA - (MethodBodiesRVA + MethodBodiesLength)); i > 0; i--)
            {
                mw.Write((byte)0);
            }

            // Resources
            moduleBuilder.WriteResources(mw);

            // The strong name signature live here (if it exists), but it will written later
            // and the following alignment padding will take care of reserving the space.

            // alignment padding
            for (int i = (int)(MetadataRVA - (ResourcesRVA + ResourcesLength)); i > 0; i--)
            {
                mw.Write((byte)0);
            }

            // Metadata
            AssertRVA(mw, MetadataRVA);
            moduleBuilder.WriteMetadata(mw, out guidHeapOffset);

            // alignment padding
            for (int i = (int)(VTableFixupsRVA - (MetadataRVA + MetadataLength)); i > 0; i--)
            {
                mw.Write((byte)0);
            }

            // VTableFixups
            AssertRVA(mw, VTableFixupsRVA);
            WriteVTableFixups(mw, sdataRVA);

            // Debug Directory
            AssertRVA(mw, DebugDirectoryRVA);
            WriteDebugDirectory(mw);

            // alignment padding
            for (int i = (int)(ExportDirectoryRVA - (DebugDirectoryRVA + DebugDirectoryLength + DebugDirectoryContentsLength)); i > 0; i--)
            {
                mw.Write((byte)0);
            }

            // Export Directory
            AssertRVA(mw, ExportDirectoryRVA);
            WriteExportDirectory(mw);

            // Export Tables
            AssertRVA(mw, ExportTablesRVA);
            WriteExportTables(mw, sdataRVA);

            // alignment padding
            for (int i = (int)(ImportDirectoryRVA - (ExportTablesRVA + ExportTablesLength)); i > 0; i--)
            {
                mw.Write((byte)0);
            }

            // Import Directory
            AssertRVA(mw, ImportDirectoryRVA);
            if (ImportDirectoryLength != 0)
            {
                WriteImportDirectory(mw);
            }

            // alignment padding
            for (int i = (int)(StartupStubRVA - (ImportDirectoryRVA + ImportDirectoryLength)); i > 0; i--)
            {
                mw.Write((byte)0);
            }

            // Startup Stub
            AssertRVA(mw, StartupStubRVA);
            if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64)
            {
                /*
                 *   48 A1 00 20 40 00 00 00 00 00        mov         rax,qword ptr [0000000000402000h]
                 *   FF E0                                jmp         rax
                 */
                mw.Write((ushort)0xA148);
                mw.Write(peWriter.Headers.OptionalHeader.ImageBase + ImportAddressTableRVA);
                mw.Write((ushort)0xE0FF);
            }
            else if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64)
            {
                mw.Write(new byte[] {
                    0x0B, 0x48, 0x00, 0x02, 0x18, 0x10, 0xA0, 0x40, 0x24, 0x30, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00,
                    0x10, 0x08, 0x00, 0x12, 0x18, 0x10, 0x60, 0x50, 0x04, 0x80, 0x03, 0x00, 0x60, 0x00, 0x80, 0x00
                });
                mw.Write(peWriter.Headers.OptionalHeader.ImageBase + StartupStubRVA);
                mw.Write(peWriter.Headers.OptionalHeader.ImageBase + BaseRVA);
            }
            else if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386)
            {
                mw.Write((ushort)0x25FF);
                mw.Write((uint)peWriter.Headers.OptionalHeader.ImageBase + ImportAddressTableRVA);
            }
            else if (peWriter.Headers.FileHeader.Machine == IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_ARM)
            {
                uint   rva = (uint)peWriter.Headers.OptionalHeader.ImageBase + ImportAddressTableRVA;
                ushort lo  = (ushort)rva;
                ushort hi  = (ushort)(rva >> 16);
                mw.Write((ushort)(0xF240 + (lo >> 12)));
                mw.Write((ushort)(0x0C00 + ((lo << 4) & 0xF000) + (lo & 0xFF)));
                mw.Write((ushort)(0xF2C0 + (hi >> 12)));
                mw.Write((ushort)(0x0C00 + ((hi << 4) & 0xF000) + (hi & 0xFF)));
                mw.Write((ushort)0xF8DC);
                mw.Write((ushort)0xF000);
            }
            else
            {
                throw new NotSupportedException();
            }
        }
Пример #17
0
			internal void WriteRelocations(MetadataWriter mw)
			{
				// we assume that unmanagedExports is still sorted by ordinal
				for (int i = 0, pos = 0; i < entries; i++)
				{
					if (text.moduleBuilder.unmanagedExports[pos].ordinal == i + ordinalBase)
					{
						// both I386 and AMD64 have the address at offset 2
						text.WriteRelocationBlock(mw, stubsRVA + 2 + (uint)pos * stubLength);
						pos++;
					}
				}
			}
Пример #18
0
		private static int GetLength(MetadataWriter mw)
		{
			int len = 4 + 4 + 8 + 8;
			foreach (Table table in mw.ModuleBuilder.GetTables())
			{
				if (table != null && table.RowCount > 0)
				{
					len += 4;	// row count
					len += table.GetLength(mw);
				}
			}
			// note that we pad one extra (unexplained) byte
			return len + 1;
		}
Пример #19
0
		private void WriteExportDirectory(MetadataWriter mw)
		{
			if (ExportDirectoryLength != 0)
			{
				// Flags
				mw.Write(0);
				// Date/Time Stamp
				mw.Write(peWriter.Headers.FileHeader.TimeDateStamp);
				// Major Version
				mw.Write((short)0);
				// Minor Version
				mw.Write((short)0);
				// Name RVA
				mw.Write(exportTables.namesRVA);
				// Ordinal Base
				mw.Write(exportTables.ordinalBase);
				// Address Table Entries
				mw.Write(exportTables.entries);
				// Number of Name Pointers
				mw.Write(exportTables.nameCount);
				// Export Address Table RVA
				mw.Write(exportTables.exportAddressTableRVA);
				// Name Pointer RVA
				mw.Write(exportTables.exportNamePointerTableRVA);
				// Ordinal Table RVA
				mw.Write(exportTables.exportOrdinalTableRVA);
			}
		}
Пример #20
0
		protected override void WriteImpl(MetadataWriter mw)
		{
			mw.Write((byte)0);
			foreach (string str in list)
			{
				mw.WriteCompressedInt(str.Length * 2 + 1);
				byte hasSpecialChars = 0;
				foreach (char ch in str)
				{
					mw.Write((ushort)ch);
					if (hasSpecialChars == 0 && (ch < 0x20 || ch > 0x7E))
					{
						if (ch > 0x7E
							|| (ch >= 0x01 && ch <= 0x08)
							|| (ch >= 0x0E && ch <= 0x1F)
							|| ch == 0x27
							|| ch == 0x2D)
						{
							hasSpecialChars = 1;
						}
					}
				}
				mw.Write(hasSpecialChars);
			}
		}
Пример #21
0
		private void WriteExportTables(MetadataWriter mw, uint sdataRVA)
		{
			if (exportTables != null)
			{
				exportTables.Write(mw, sdataRVA);
			}
		}
Пример #22
0
		private void WriteImportDirectory(MetadataWriter mw)
		{
			mw.Write(ImportDirectoryRVA + 40);		// ImportLookupTable
			mw.Write(0);							// DateTimeStamp
			mw.Write(0);							// ForwarderChain
			mw.Write(ImportHintNameTableRVA + 14);	// Name
			mw.Write(ImportAddressTableRVA);
			mw.Write(new byte[20]);
			// Import Lookup Table
			mw.Write(ImportHintNameTableRVA);		// Hint/Name Table RVA
			int size = 48;
			if (peWriter.Headers.FileHeader.Machine != IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386)
			{
				size += 4;
				mw.Write(0);
			}
			mw.Write(0);

			// alignment padding
			for (int i = (int)(ImportHintNameTableRVA - (ImportDirectoryRVA + size)); i > 0; i--)
			{
				mw.Write((byte)0);
			}

			// Hint/Name Table
			AssertRVA(mw, ImportHintNameTableRVA);
			mw.Write((ushort)0);		// Hint
			if ((peWriter.Headers.FileHeader.Characteristics & IMAGE_FILE_HEADER.IMAGE_FILE_DLL) != 0)
			{
				mw.Write(System.Text.Encoding.ASCII.GetBytes("_CorDllMain"));
			}
			else
			{
				mw.Write(System.Text.Encoding.ASCII.GetBytes("_CorExeMain"));
			}
			mw.Write((byte)0);
			// Name
			mw.Write(System.Text.Encoding.ASCII.GetBytes("mscoree.dll"));
			mw.Write((ushort)0);
		}
Пример #23
0
		internal void WriteRelocations(MetadataWriter mw)
		{
			uint relocAddress = this.StartupStubRVA;
			switch (peWriter.Headers.FileHeader.Machine)
			{
				case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386:
				case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64:
					relocAddress += 2;
					break;
				case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64:
					relocAddress += 0x20;
					break;
			}
			WriteRelocationBlock(mw, relocAddress);
			if (exportTables != null)
			{
				exportTables.WriteRelocations(mw);
			}
		}
Пример #24
0
		protected abstract void WriteImpl(MetadataWriter mw);
Пример #25
0
		// note that we're lazy and write a new relocation block for every relocation
		// even if they are in the same page (since there is typically only one anyway)
		private void WriteRelocationBlock(MetadataWriter mw, uint relocAddress)
		{
			uint pageRVA = relocAddress & ~0xFFFU;
			mw.Write(pageRVA);	// PageRVA
			mw.Write(0x000C);	// Block Size
			switch (peWriter.Headers.FileHeader.Machine)
			{
				case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386:
					mw.Write(0x3000 + relocAddress - pageRVA);				// Type / Offset
					break;
				case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64:
					mw.Write(0xA000 + relocAddress - pageRVA);				// Type / Offset
					break;
				case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64:
					// on IA64 the StartupStubRVA is 16 byte aligned, so these two addresses won't cross a page boundary
					mw.Write((short)(0xA000 + relocAddress - pageRVA));		// Type / Offset
					mw.Write((short)(0xA000 + relocAddress - pageRVA + 8));	// Type / Offset
					break;
			}
		}
Пример #26
0
		protected override void WriteImpl(MetadataWriter mw)
		{
			Table[] tables = mw.ModuleBuilder.GetTables();
			// Header
			mw.Write(0);		// Reserved
			int ver = mw.ModuleBuilder.MDStreamVersion;
			mw.Write((byte)(ver >> 16));	// MajorVersion
			mw.Write((byte)ver);			// MinorVersion
			byte heapSizes = 0;
			if (mw.ModuleBuilder.Strings.IsBig)
			{
				heapSizes |= 0x01;
			}
			if (mw.ModuleBuilder.Guids.IsBig)
			{
				heapSizes |= 0x02;
			}
			if (mw.ModuleBuilder.Blobs.IsBig)
			{
				heapSizes |= 0x04;
			}
			mw.Write(heapSizes);// HeapSizes
			// LAMESPEC spec says reserved, but .NET 2.0 Ref.Emit sets it to 0x10
			mw.Write((byte)0x10);	// Reserved
			long bit = 1;
			long valid = 0;
			foreach (Table table in tables)
			{
				if (table != null && table.RowCount > 0)
				{
					valid |= bit;
				}
				bit <<= 1;
			}
			mw.Write(valid);	// Valid
			mw.Write(0x0016003301FA00L);	// Sorted
			// Rows
			foreach (Table table in tables)
			{
				if (table != null && table.RowCount > 0)
				{
					mw.Write(table.RowCount);
				}
			}
			// Tables
			foreach (Table table in tables)
			{
				if (table != null && table.RowCount > 0)
				{
					int pos = mw.Position;
					table.Write(mw);
					Debug.Assert(mw.Position - pos == table.GetLength(mw));
				}
			}
			// unexplained extra padding
			mw.Write((byte)0);
		}
Пример #27
0
		internal void WriteFieldRecords(MetadataWriter mw)
		{
			mw.Write((short)attribs);
			mw.WriteStringIndex(nameIndex);
			mw.WriteBlobIndex(signature);
		}
Пример #28
0
		internal void WriteParamRecords(MetadataWriter mw)
		{
			if (parameters != null)
			{
				foreach (ParameterBuilder pb in parameters)
				{
					pb.WriteParamRecord(mw);
				}
			}
		}
Пример #29
0
		internal static void WriteModule(StrongNameKeyPair keyPair, byte[] publicKey, ModuleBuilder moduleBuilder, PEFileKinds fileKind, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine, ByteBuffer versionInfoData, byte[] unmanagedResources, int entryPointToken)
		{
			moduleBuilder.FixupMethodBodyTokens();

			moduleBuilder.ModuleTable.Add(0, moduleBuilder.Strings.Add(moduleBuilder.moduleName), moduleBuilder.Guids.Add(moduleBuilder.ModuleVersionId), 0, 0);

			if (moduleBuilder.UserStrings.IsEmpty)
			{
				// for compat with Ref.Emit, if there aren't any user strings, we add one
				moduleBuilder.UserStrings.Add(" ");
			}

			using (FileStream fs = new FileStream(moduleBuilder.FullyQualifiedName, FileMode.Create))
			{
				PEWriter writer = new PEWriter(fs);
				switch (imageFileMachine)
				{
					case ImageFileMachine.I386:
						writer.Headers.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386;
						writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_32BIT_MACHINE;
						break;
					case ImageFileMachine.AMD64:
						writer.Headers.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64;
						writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_LARGE_ADDRESS_AWARE;
						writer.Headers.FileHeader.SizeOfOptionalHeader = 0xF0;
						writer.Headers.OptionalHeader.Magic = IMAGE_OPTIONAL_HEADER.IMAGE_NT_OPTIONAL_HDR64_MAGIC;
						writer.Headers.OptionalHeader.SizeOfStackReserve = 0x400000;
						writer.Headers.OptionalHeader.SizeOfStackCommit = 0x4000;
						writer.Headers.OptionalHeader.SizeOfHeapCommit = 0x2000;
						break;
					case ImageFileMachine.IA64:
						writer.Headers.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64;
						writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_LARGE_ADDRESS_AWARE;
						writer.Headers.FileHeader.SizeOfOptionalHeader = 0xF0;
						writer.Headers.OptionalHeader.Magic = IMAGE_OPTIONAL_HEADER.IMAGE_NT_OPTIONAL_HDR64_MAGIC;
						writer.Headers.OptionalHeader.SizeOfStackReserve = 0x400000;
						writer.Headers.OptionalHeader.SizeOfStackCommit = 0x4000;
						writer.Headers.OptionalHeader.SizeOfHeapCommit = 0x2000;
						break;
					default:
						throw new ArgumentOutOfRangeException("imageFileMachine");
				}
				if (fileKind == PEFileKinds.Dll)
				{
					writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_DLL;
				}

				switch (fileKind)
				{
					case PEFileKinds.WindowApplication:
						writer.Headers.OptionalHeader.Subsystem = IMAGE_OPTIONAL_HEADER.IMAGE_SUBSYSTEM_WINDOWS_GUI;
						break;
					default:
						writer.Headers.OptionalHeader.Subsystem = IMAGE_OPTIONAL_HEADER.IMAGE_SUBSYSTEM_WINDOWS_CUI;
						break;
				}
				writer.Headers.OptionalHeader.DllCharacteristics =
					IMAGE_OPTIONAL_HEADER.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE |
					IMAGE_OPTIONAL_HEADER.IMAGE_DLLCHARACTERISTICS_NO_SEH |
					IMAGE_OPTIONAL_HEADER.IMAGE_DLLCHARACTERISTICS_NX_COMPAT |
					IMAGE_OPTIONAL_HEADER.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE;

				CliHeader cliHeader = new CliHeader();
				cliHeader.Cb = 0x48;
				cliHeader.MajorRuntimeVersion = 2;
				cliHeader.MinorRuntimeVersion = moduleBuilder.MDStreamVersion < 0x20000 ? (ushort)0 : (ushort)5;
				if ((portableExecutableKind & PortableExecutableKinds.ILOnly) != 0)
				{
					cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_ILONLY;
				}
				if ((portableExecutableKind & PortableExecutableKinds.Required32Bit) != 0)
				{
					cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_32BITREQUIRED;
				}
				if (keyPair != null)
				{
					cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_STRONGNAMESIGNED;
				}
				if (moduleBuilder.IsPseudoToken(entryPointToken))
				{
					entryPointToken = moduleBuilder.ResolvePseudoToken(entryPointToken);
				}
				cliHeader.EntryPointToken = (uint)entryPointToken;

				moduleBuilder.Strings.Freeze();
				moduleBuilder.UserStrings.Freeze();
				moduleBuilder.Guids.Freeze();
				moduleBuilder.Blobs.Freeze();
				MetadataWriter mw = new MetadataWriter(moduleBuilder, fs);
				moduleBuilder.Tables.Freeze(mw);
				TextSection code = new TextSection(writer, cliHeader, moduleBuilder, publicKey != null);
				ResourceSection resources = new ResourceSection(versionInfoData, unmanagedResources);

				// Import Directory
				writer.Headers.OptionalHeader.DataDirectory[1].VirtualAddress = code.ImportDirectoryRVA;
				writer.Headers.OptionalHeader.DataDirectory[1].Size = code.ImportDirectoryLength;

				// Import Address Table Directory
				writer.Headers.OptionalHeader.DataDirectory[12].VirtualAddress = code.ImportAddressTableRVA;
				writer.Headers.OptionalHeader.DataDirectory[12].Size = code.ImportAddressTableLength;

				// COM Descriptor Directory
				writer.Headers.OptionalHeader.DataDirectory[14].VirtualAddress = code.ComDescriptorRVA;
				writer.Headers.OptionalHeader.DataDirectory[14].Size = code.ComDescriptorLength;

				// Debug Directory
				if (code.DebugDirectoryLength != 0)
				{
					writer.Headers.OptionalHeader.DataDirectory[6].VirtualAddress = code.DebugDirectoryRVA;
					writer.Headers.OptionalHeader.DataDirectory[6].Size = code.DebugDirectoryLength;
				}

				writer.Headers.FileHeader.NumberOfSections = 2;

				if (moduleBuilder.initializedData.Length != 0)
				{
					writer.Headers.FileHeader.NumberOfSections++;
				}

				if (resources.Length != 0)
				{
					writer.Headers.FileHeader.NumberOfSections++;
				}

				SectionHeader text = new SectionHeader();
				text.Name = ".text";
				text.VirtualAddress = code.BaseRVA;
				text.VirtualSize = (uint)code.Length;
				text.PointerToRawData = code.PointerToRawData;
				text.SizeOfRawData = writer.ToFileAlignment((uint)code.Length);
				text.Characteristics = SectionHeader.IMAGE_SCN_CNT_CODE | SectionHeader.IMAGE_SCN_MEM_EXECUTE | SectionHeader.IMAGE_SCN_MEM_READ;

				SectionHeader sdata = new SectionHeader();
				sdata.Name = ".sdata";
				sdata.VirtualAddress = text.VirtualAddress + writer.ToSectionAlignment(text.VirtualSize);
				sdata.VirtualSize = (uint)moduleBuilder.initializedData.Length;
				sdata.PointerToRawData = text.PointerToRawData + text.SizeOfRawData;
				sdata.SizeOfRawData = writer.ToFileAlignment((uint)moduleBuilder.initializedData.Length);
				sdata.Characteristics = SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA | SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_MEM_WRITE;

				SectionHeader rsrc = new SectionHeader();
				rsrc.Name = ".rsrc";
				rsrc.VirtualAddress = sdata.VirtualAddress + writer.ToSectionAlignment(sdata.VirtualSize);
				rsrc.PointerToRawData = sdata.PointerToRawData + sdata.SizeOfRawData;
				rsrc.VirtualSize = (uint)resources.Length;
				rsrc.SizeOfRawData = writer.ToFileAlignment(rsrc.VirtualSize);
				rsrc.Characteristics = SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA;

				if (rsrc.SizeOfRawData != 0)
				{
					// Resource Directory
					writer.Headers.OptionalHeader.DataDirectory[2].VirtualAddress = rsrc.VirtualAddress;
					writer.Headers.OptionalHeader.DataDirectory[2].Size = rsrc.VirtualSize;
				}

				SectionHeader reloc = new SectionHeader();
				reloc.Name = ".reloc";
				reloc.VirtualAddress = rsrc.VirtualAddress + writer.ToSectionAlignment(rsrc.VirtualSize);
				reloc.VirtualSize = 12;
				reloc.PointerToRawData = rsrc.PointerToRawData + rsrc.SizeOfRawData;
				reloc.SizeOfRawData = writer.ToFileAlignment(reloc.VirtualSize);
				reloc.Characteristics = SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA | SectionHeader.IMAGE_SCN_MEM_DISCARDABLE;

				// Base Relocation Directory
				writer.Headers.OptionalHeader.DataDirectory[5].VirtualAddress = reloc.VirtualAddress;
				writer.Headers.OptionalHeader.DataDirectory[5].Size = reloc.VirtualSize;

				writer.Headers.OptionalHeader.SizeOfCode = text.SizeOfRawData;
				writer.Headers.OptionalHeader.SizeOfInitializedData = sdata.SizeOfRawData + rsrc.SizeOfRawData + reloc.SizeOfRawData;
				writer.Headers.OptionalHeader.SizeOfUninitializedData = 0;
				writer.Headers.OptionalHeader.SizeOfImage = reloc.VirtualAddress + writer.ToSectionAlignment(reloc.VirtualSize);
				writer.Headers.OptionalHeader.SizeOfHeaders = text.PointerToRawData;
				writer.Headers.OptionalHeader.BaseOfCode = code.BaseRVA;
				writer.Headers.OptionalHeader.BaseOfData = sdata.VirtualAddress;
				writer.Headers.OptionalHeader.ImageBase = (ulong)moduleBuilder.__ImageBase;

				if (imageFileMachine == ImageFileMachine.IA64)
				{
					// apparently for IA64 AddressOfEntryPoint points to the address of the entry point
					// (i.e. there is an additional layer of indirection), so we add the offset to the pointer
					writer.Headers.OptionalHeader.AddressOfEntryPoint = code.StartupStubRVA + 0x20;
				}
				else
				{
					writer.Headers.OptionalHeader.AddressOfEntryPoint = code.StartupStubRVA;
				}

				writer.WritePEHeaders();
				writer.WriteSectionHeader(text);
				if (sdata.SizeOfRawData != 0)
				{
					writer.WriteSectionHeader(sdata);
				}
				if (rsrc.SizeOfRawData != 0)
				{
					writer.WriteSectionHeader(rsrc);
				}
				writer.WriteSectionHeader(reloc);

				fs.Seek(text.PointerToRawData, SeekOrigin.Begin);
				code.Write(mw, (int)sdata.VirtualAddress);

				fs.Seek(sdata.PointerToRawData, SeekOrigin.Begin);
				mw.Write(moduleBuilder.initializedData);

				if (rsrc.SizeOfRawData != 0)
				{
					fs.Seek(rsrc.PointerToRawData, SeekOrigin.Begin);
					resources.Write(mw, rsrc.VirtualAddress);
				}

				fs.Seek(reloc.PointerToRawData, SeekOrigin.Begin);
				// .reloc section
				uint relocAddress = code.StartupStubRVA;
				switch (imageFileMachine)
				{
					case ImageFileMachine.I386:
					case ImageFileMachine.AMD64:
						relocAddress += 2;
						break;
					case ImageFileMachine.IA64:
						relocAddress += 0x20;
						break;
				}
				uint pageRVA = relocAddress & ~0xFFFU;
				mw.Write(pageRVA);	// PageRVA
				mw.Write(0x000C);	// Block Size
				if (imageFileMachine == ImageFileMachine.I386)
				{
					mw.Write(0x3000 + relocAddress - pageRVA);				// Type / Offset
				}
				else if (imageFileMachine == ImageFileMachine.AMD64)
				{
					mw.Write(0xA000 + relocAddress - pageRVA);				// Type / Offset
				}
				else if (imageFileMachine == ImageFileMachine.IA64)
				{
					// on IA64 the StartupStubRVA is 16 byte aligned, so these two addresses won't cross a page boundary
					mw.Write((short)(0xA000 + relocAddress - pageRVA));		// Type / Offset
					mw.Write((short)(0xA000 + relocAddress - pageRVA + 8));	// Type / Offset
				}

				// file alignment
				mw.Write(new byte[writer.Headers.OptionalHeader.FileAlignment - reloc.VirtualSize]);

				// do the strong naming
				if (keyPair != null)
				{
					StrongName(fs, keyPair, writer.HeaderSize, text.PointerToRawData, code.StrongNameSignatureRVA - text.VirtualAddress + text.PointerToRawData, code.StrongNameSignatureLength);
				}
			}

			if (moduleBuilder.symbolWriter != null)
			{
				moduleBuilder.WriteSymbolTokenMap();
				moduleBuilder.symbolWriter.Close();
			}
		}
Пример #30
0
		internal void WriteMethodDefRecords(int baseRVA, MetadataWriter mw, ref int paramList)
		{
			foreach (MethodBuilder mb in methods)
			{
				mb.WriteMethodDefRecord(baseRVA, mw, ref paramList);
			}
		}
		internal void WriteParamRecord(MetadataWriter mw)
		{
			mw.Write(flags);
			mw.Write(sequence);
			mw.WriteStringIndex(nameIndex);
		}
Пример #32
0
		internal void WriteFieldRecords(MetadataWriter mw)
		{
			foreach (FieldBuilder fb in fields)
			{
				fb.WriteFieldRecords(mw);
			}
		}
Пример #33
0
        private static void WriteModuleImpl(StrongNameKeyPair keyPair, byte[] publicKey, ModuleBuilder moduleBuilder,
                                            PEFileKinds fileKind, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine,
                                            ResourceSection resources, int entryPointToken, Stream stream)
        {
            moduleBuilder.ApplyUnmanagedExports(imageFileMachine);
            moduleBuilder.FixupMethodBodyTokens();

            int moduleVersionIdIndex = moduleBuilder.Guids.Add(moduleBuilder.GetModuleVersionIdOrEmpty());

            moduleBuilder.ModuleTable.Add(0, moduleBuilder.Strings.Add(moduleBuilder.moduleName), moduleVersionIdIndex, 0, 0);

            if (moduleBuilder.UserStrings.IsEmpty)
            {
                // for compat with Ref.Emit, if there aren't any user strings, we add one
                moduleBuilder.UserStrings.Add(" ");
            }

            if (resources != null)
            {
                resources.Finish();
            }

            PEWriter writer = new PEWriter(stream);

            writer.Headers.OptionalHeader.FileAlignment = (uint)moduleBuilder.__FileAlignment;
            switch (imageFileMachine)
            {
            case ImageFileMachine.I386:
                writer.Headers.FileHeader.Machine                = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386;
                writer.Headers.FileHeader.Characteristics       |= IMAGE_FILE_HEADER.IMAGE_FILE_32BIT_MACHINE;
                writer.Headers.OptionalHeader.SizeOfStackReserve = moduleBuilder.GetStackReserve(0x100000);
                break;

            case ImageFileMachine.ARM:
                writer.Headers.FileHeader.Machine                = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_ARM;
                writer.Headers.FileHeader.Characteristics       |= IMAGE_FILE_HEADER.IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_HEADER.IMAGE_FILE_LARGE_ADDRESS_AWARE;
                writer.Headers.OptionalHeader.SizeOfStackReserve = moduleBuilder.GetStackReserve(0x100000);
                writer.Headers.OptionalHeader.SectionAlignment   = 0x1000;
                break;

            case ImageFileMachine.AMD64:
                writer.Headers.FileHeader.Machine                = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64;
                writer.Headers.FileHeader.Characteristics       |= IMAGE_FILE_HEADER.IMAGE_FILE_LARGE_ADDRESS_AWARE;
                writer.Headers.FileHeader.SizeOfOptionalHeader   = 0xF0;
                writer.Headers.OptionalHeader.Magic              = IMAGE_OPTIONAL_HEADER.IMAGE_NT_OPTIONAL_HDR64_MAGIC;
                writer.Headers.OptionalHeader.SizeOfStackReserve = moduleBuilder.GetStackReserve(0x400000);
                writer.Headers.OptionalHeader.SizeOfStackCommit  = 0x4000;
                writer.Headers.OptionalHeader.SizeOfHeapCommit   = 0x2000;
                break;

            case ImageFileMachine.IA64:
                writer.Headers.FileHeader.Machine                = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_IA64;
                writer.Headers.FileHeader.Characteristics       |= IMAGE_FILE_HEADER.IMAGE_FILE_LARGE_ADDRESS_AWARE;
                writer.Headers.FileHeader.SizeOfOptionalHeader   = 0xF0;
                writer.Headers.OptionalHeader.Magic              = IMAGE_OPTIONAL_HEADER.IMAGE_NT_OPTIONAL_HDR64_MAGIC;
                writer.Headers.OptionalHeader.SizeOfStackReserve = moduleBuilder.GetStackReserve(0x400000);
                writer.Headers.OptionalHeader.SizeOfStackCommit  = 0x4000;
                writer.Headers.OptionalHeader.SizeOfHeapCommit   = 0x2000;
                break;

            default:
                throw new ArgumentOutOfRangeException("imageFileMachine");
            }
            if (fileKind == PEFileKinds.Dll)
            {
                writer.Headers.FileHeader.Characteristics |= IMAGE_FILE_HEADER.IMAGE_FILE_DLL;
            }

            switch (fileKind)
            {
            case PEFileKinds.WindowApplication:
                writer.Headers.OptionalHeader.Subsystem = IMAGE_OPTIONAL_HEADER.IMAGE_SUBSYSTEM_WINDOWS_GUI;
                break;

            default:
                writer.Headers.OptionalHeader.Subsystem = IMAGE_OPTIONAL_HEADER.IMAGE_SUBSYSTEM_WINDOWS_CUI;
                break;
            }
            writer.Headers.OptionalHeader.DllCharacteristics = (ushort)moduleBuilder.__DllCharacteristics;

            CliHeader cliHeader = new CliHeader();

            cliHeader.Cb = 0x48;
            cliHeader.MajorRuntimeVersion = 2;
            cliHeader.MinorRuntimeVersion = moduleBuilder.MDStreamVersion < 0x20000 ? (ushort)0 : (ushort)5;
            if ((portableExecutableKind & PortableExecutableKinds.ILOnly) != 0)
            {
                cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_ILONLY;
            }
            if ((portableExecutableKind & PortableExecutableKinds.Required32Bit) != 0)
            {
                cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_32BITREQUIRED;
            }
            if ((portableExecutableKind & PortableExecutableKinds.Preferred32Bit) != 0)
            {
                cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_32BITREQUIRED | CliHeader.COMIMAGE_FLAGS_32BITPREFERRED;
            }
            if (keyPair != null)
            {
                cliHeader.Flags |= CliHeader.COMIMAGE_FLAGS_STRONGNAMESIGNED;
            }
            if (ModuleBuilder.IsPseudoToken(entryPointToken))
            {
                entryPointToken = moduleBuilder.ResolvePseudoToken(entryPointToken);
            }
            cliHeader.EntryPointToken = (uint)entryPointToken;

            moduleBuilder.Strings.Freeze();
            moduleBuilder.UserStrings.Freeze();
            moduleBuilder.Guids.Freeze();
            moduleBuilder.Blobs.Freeze();
            MetadataWriter mw = new MetadataWriter(moduleBuilder, stream);

            moduleBuilder.Tables.Freeze(mw);
            TextSection code = new TextSection(writer, cliHeader, moduleBuilder, ComputeStrongNameSignatureLength(publicKey));

            // Export Directory
            if (code.ExportDirectoryLength != 0)
            {
                writer.Headers.OptionalHeader.DataDirectory[0].VirtualAddress = code.ExportDirectoryRVA;
                writer.Headers.OptionalHeader.DataDirectory[0].Size           = code.ExportDirectoryLength;
            }

            // Import Directory
            if (code.ImportDirectoryLength != 0)
            {
                writer.Headers.OptionalHeader.DataDirectory[1].VirtualAddress = code.ImportDirectoryRVA;
                writer.Headers.OptionalHeader.DataDirectory[1].Size           = code.ImportDirectoryLength;
            }

            // Import Address Table Directory
            if (code.ImportAddressTableLength != 0)
            {
                writer.Headers.OptionalHeader.DataDirectory[12].VirtualAddress = code.ImportAddressTableRVA;
                writer.Headers.OptionalHeader.DataDirectory[12].Size           = code.ImportAddressTableLength;
            }

            // COM Descriptor Directory
            writer.Headers.OptionalHeader.DataDirectory[14].VirtualAddress = code.ComDescriptorRVA;
            writer.Headers.OptionalHeader.DataDirectory[14].Size           = code.ComDescriptorLength;

            // Debug Directory
            if (code.DebugDirectoryLength != 0)
            {
                writer.Headers.OptionalHeader.DataDirectory[6].VirtualAddress = code.DebugDirectoryRVA;
                writer.Headers.OptionalHeader.DataDirectory[6].Size           = code.DebugDirectoryLength;
            }

            // Set the PE File timestamp
            writer.Headers.FileHeader.TimeDateStamp = moduleBuilder.GetTimeDateStamp();

            // we need to start by computing the number of sections, because code.PointerToRawData depends on that
            writer.Headers.FileHeader.NumberOfSections = 2;

            if (moduleBuilder.initializedData.Length != 0)
            {
                // .sdata
                writer.Headers.FileHeader.NumberOfSections++;
            }

            if (resources != null)
            {
                // .rsrc
                writer.Headers.FileHeader.NumberOfSections++;
            }

            SectionHeader text = new SectionHeader();

            text.Name             = ".text";
            text.VirtualAddress   = code.BaseRVA;
            text.VirtualSize      = (uint)code.Length;
            text.PointerToRawData = code.PointerToRawData;
            text.SizeOfRawData    = writer.ToFileAlignment((uint)code.Length);
            text.Characteristics  = SectionHeader.IMAGE_SCN_CNT_CODE | SectionHeader.IMAGE_SCN_MEM_EXECUTE | SectionHeader.IMAGE_SCN_MEM_READ;

            SectionHeader sdata = new SectionHeader();

            sdata.Name             = ".sdata";
            sdata.VirtualAddress   = text.VirtualAddress + writer.ToSectionAlignment(text.VirtualSize);
            sdata.VirtualSize      = (uint)moduleBuilder.initializedData.Length;
            sdata.PointerToRawData = text.PointerToRawData + text.SizeOfRawData;
            sdata.SizeOfRawData    = writer.ToFileAlignment((uint)moduleBuilder.initializedData.Length);
            sdata.Characteristics  = SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA | SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_MEM_WRITE;

            SectionHeader rsrc = new SectionHeader();

            rsrc.Name             = ".rsrc";
            rsrc.VirtualAddress   = sdata.VirtualAddress + writer.ToSectionAlignment(sdata.VirtualSize);
            rsrc.PointerToRawData = sdata.PointerToRawData + sdata.SizeOfRawData;
            rsrc.VirtualSize      = resources == null ? 0 : (uint)resources.Length;
            rsrc.SizeOfRawData    = writer.ToFileAlignment(rsrc.VirtualSize);
            rsrc.Characteristics  = SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA;

            if (rsrc.SizeOfRawData != 0)
            {
                // Resource Directory
                writer.Headers.OptionalHeader.DataDirectory[2].VirtualAddress = rsrc.VirtualAddress;
                writer.Headers.OptionalHeader.DataDirectory[2].Size           = rsrc.VirtualSize;
            }

            SectionHeader reloc = new SectionHeader();

            reloc.Name             = ".reloc";
            reloc.VirtualAddress   = rsrc.VirtualAddress + writer.ToSectionAlignment(rsrc.VirtualSize);
            reloc.VirtualSize      = code.PackRelocations();
            reloc.PointerToRawData = rsrc.PointerToRawData + rsrc.SizeOfRawData;
            reloc.SizeOfRawData    = writer.ToFileAlignment(reloc.VirtualSize);
            reloc.Characteristics  = SectionHeader.IMAGE_SCN_MEM_READ | SectionHeader.IMAGE_SCN_CNT_INITIALIZED_DATA | SectionHeader.IMAGE_SCN_MEM_DISCARDABLE;

            if (reloc.SizeOfRawData != 0)
            {
                // Base Relocation Directory
                writer.Headers.OptionalHeader.DataDirectory[5].VirtualAddress = reloc.VirtualAddress;
                writer.Headers.OptionalHeader.DataDirectory[5].Size           = reloc.VirtualSize;
            }

            writer.Headers.OptionalHeader.SizeOfCode              = text.SizeOfRawData;
            writer.Headers.OptionalHeader.SizeOfInitializedData   = sdata.SizeOfRawData + rsrc.SizeOfRawData + reloc.SizeOfRawData;
            writer.Headers.OptionalHeader.SizeOfUninitializedData = 0;
            writer.Headers.OptionalHeader.SizeOfImage             = reloc.VirtualAddress + writer.ToSectionAlignment(reloc.VirtualSize);
            writer.Headers.OptionalHeader.SizeOfHeaders           = text.PointerToRawData;
            writer.Headers.OptionalHeader.BaseOfCode              = code.BaseRVA;
            writer.Headers.OptionalHeader.BaseOfData              = sdata.VirtualAddress;
            writer.Headers.OptionalHeader.ImageBase = (ulong)moduleBuilder.__ImageBase;

            if (imageFileMachine == ImageFileMachine.IA64)
            {
                // apparently for IA64 AddressOfEntryPoint points to the address of the entry point
                // (i.e. there is an additional layer of indirection), so we add the offset to the pointer
                writer.Headers.OptionalHeader.AddressOfEntryPoint = code.StartupStubRVA + 0x20;
            }
            else
            {
                writer.Headers.OptionalHeader.AddressOfEntryPoint = code.StartupStubRVA + writer.Thumb;
            }

            writer.WritePEHeaders();
            writer.WriteSectionHeader(text);
            if (sdata.SizeOfRawData != 0)
            {
                writer.WriteSectionHeader(sdata);
            }
            if (rsrc.SizeOfRawData != 0)
            {
                writer.WriteSectionHeader(rsrc);
            }
            if (reloc.SizeOfRawData != 0)
            {
                writer.WriteSectionHeader(reloc);
            }

            stream.Seek(text.PointerToRawData, SeekOrigin.Begin);
            uint guidHeapOffset;

            code.Write(mw, sdata.VirtualAddress, out guidHeapOffset);

            if (sdata.SizeOfRawData != 0)
            {
                stream.Seek(sdata.PointerToRawData, SeekOrigin.Begin);
                mw.Write(moduleBuilder.initializedData);
            }

            if (rsrc.SizeOfRawData != 0)
            {
                stream.Seek(rsrc.PointerToRawData, SeekOrigin.Begin);
                resources.Write(mw, rsrc.VirtualAddress);
            }

            if (reloc.SizeOfRawData != 0)
            {
                stream.Seek(reloc.PointerToRawData, SeekOrigin.Begin);
                code.WriteRelocations(mw);
            }

            // file alignment
            stream.SetLength(reloc.PointerToRawData + reloc.SizeOfRawData);

            // if we don't have a guid, generate one based on the contents of the assembly
            if (moduleBuilder.universe.Deterministic && moduleBuilder.GetModuleVersionIdOrEmpty() == Guid.Empty)
            {
                Guid guid = GenerateModuleVersionId(stream);
                stream.Position = guidHeapOffset + (moduleVersionIdIndex - 1) * 16;
                stream.Write(guid.ToByteArray(), 0, 16);
                moduleBuilder.__SetModuleVersionId(guid);
            }

            // do the strong naming
            if (keyPair != null)
            {
                StrongName(stream, keyPair, writer.HeaderSize, text.PointerToRawData, code.StrongNameSignatureRVA - text.VirtualAddress + text.PointerToRawData, code.StrongNameSignatureLength);
            }

#if !NO_SYMBOL_WRITER
            if (moduleBuilder.symbolWriter != null)
            {
                moduleBuilder.WriteSymbolTokenMap();
                moduleBuilder.symbolWriter.Close();
            }
#endif
        }