/// <summary> /// Writes the Cil _header. /// </summary> /// <param name="compiler">The assembly compiler.</param> /// <param name="linker">The linker.</param> private void WriteCilHeader(AssemblyCompiler compiler, IAssemblyLinker linker) { using (Stream stream = linker.Allocate(CLI_HEADER.SymbolName, SectionKind.Text, CLI_HEADER.Length, 4)) using (BinaryWriter bw = new BinaryWriter(stream, Encoding.ASCII)) { _cliHeader.Write(bw); } }
private void AskLinkerToCreateMethodTable(string methodTableName, IList <RuntimeMethod> methodTable, IList <string> headerlinks) { int methodTableSize = ((headerlinks == null ? 0 : headerlinks.Count) + (methodTable == null ? 0 : methodTable.Count)) * typeLayout.NativePointerSize; Debug.WriteLine("Method Table: " + methodTableName); using (Stream stream = linker.Allocate(methodTableName, SectionKind.Text, methodTableSize, typeLayout.NativePointerAlignment)) { stream.Position = methodTableSize; } int offset = 0; if (headerlinks != null) { foreach (string link in headerlinks) { if (!string.IsNullOrEmpty(link)) { Debug.WriteLine(" # " + (offset / typeLayout.NativePointerSize).ToString() + " " + link); linker.Link(LinkType.AbsoluteAddress | LinkType.I4, methodTableName, offset, 0, link, IntPtr.Zero); } else { Debug.WriteLine(" # " + (offset / typeLayout.NativePointerSize).ToString() + " [null]"); } offset += typeLayout.NativePointerSize; } } if (methodTable != null) { foreach (RuntimeMethod method in methodTable) { if (!method.IsAbstract) { Debug.WriteLine(" # " + (offset / typeLayout.NativePointerSize).ToString() + " " + method.ToString()); linker.Link(LinkType.AbsoluteAddress | LinkType.I4, methodTableName, offset, 0, method.ToString(), IntPtr.Zero); } else { Debug.WriteLine(" # " + (offset / typeLayout.NativePointerSize).ToString() + " [null]"); } offset += typeLayout.NativePointerSize; } } }
/// <summary> /// Writes the multiboot _header. /// </summary> /// <param name="compiler">The assembly compiler.</param> /// <param name="linker">The linker.</param> /// <param name="entryPoint">The virtualAddress of the multiboot compliant entry point.</param> private void WriteMultibootHeader(AssemblyCompiler compiler, IAssemblyLinker linker, IntPtr entryPoint) { // HACK: According to the multiboot specification this _header must be within the first 8K of the // kernel binary. Since the text section is always first, this should take care of the problem. using (Stream stream = linker.Allocate(MultibootHeaderSymbolName, SectionKind.Text, 64, 4)) using (BinaryWriter bw = new BinaryWriter(stream, Encoding.ASCII)) { // flags - multiboot flags uint flags = /*HEADER_MB_FLAG_VIDEO_MODES_REQUIRED | */ HEADER_MB_FLAG_MEMORY_INFO_REQUIRED | HEADER_MB_FLAG_MODULES_PAGE_ALIGNED; // The multiboot _header checksum uint csum = 0; // header_addr is the load virtualAddress of the multiboot _header uint header_addr = 0; // load_addr is the base virtualAddress of the binary in memory uint load_addr = 0; // load_end_addr holds the virtualAddress past the last byte to load From the image uint load_end_addr = 0; // bss_end_addr is the virtualAddress of the last byte to be zeroed out uint bss_end_addr = 0; // entry_point the load virtualAddress of the entry point to invoke uint entry_point = (uint)entryPoint.ToInt32(); // Are we linking an ELF binary? if (!(linker is Elf32Linker || linker is Elf64Linker)) { // Check the linker layout settings if (linker.LoadSectionAlignment != linker.VirtualSectionAlignment) { throw new LinkerException(@"Load and virtual section alignment must be identical if you are booting non-ELF binaries with a multiboot bootloader."); } // No, special multiboot treatment required flags |= HEADER_MB_FLAG_NON_ELF_BINARY; header_addr = (uint)(linker.GetSection(SectionKind.Text).VirtualAddress.ToInt64() + linker.GetSymbol(MultibootHeaderSymbolName).SectionAddress); load_addr = (uint)linker.BaseAddress; load_end_addr = 0; bss_end_addr = 0; } // Calculate the checksum csum = unchecked (0U - HEADER_MB_MAGIC - flags); bw.Write(HEADER_MB_MAGIC); bw.Write(flags); bw.Write(csum); bw.Write(header_addr); bw.Write(load_addr); bw.Write(load_end_addr); bw.Write(bss_end_addr); // HACK: Symbol has been hacked. What's the correct way to do this? linker.Link(LinkType.AbsoluteAddress | LinkType.I4, MultibootHeaderSymbolName, (int)stream.Position, 0, @"Mosa.Tools.Compiler.LinkerGenerated.<$>MultibootInit()", IntPtr.Zero); bw.Write(videoMode); bw.Write(videoWidth); bw.Write(videoHeight); bw.Write(videoDepth); } }
private void AllocateSpace(IAssemblyLinker linker, RuntimeField field, SectionKind section, int size, int alignment) { using (Stream stream = linker.Allocate(field, section, size, alignment)) { if (IntPtr.Zero != field.RVA) { InitializeStaticValueFromRVA(stream, size, field); } else { WriteDummyBytes(stream, size); } } }
/// <summary> /// Exports the CIL metadata. /// </summary> /// <param name="module">The module.</param> /// <param name="linker">The linker.</param> private void ExportCilMetadata(IMetadataModule module, IAssemblyLinker linker) { /* * FIXME: * - Obtain CIL & MOSA metadata tables * - Write metadata root * - Write the CIL tables (modified) * - Write the MOSA tables (new) * - Write the strings, guid and blob heap (unchanged From original module) */ // Metadata is in the .text section in order to make it relocatable everywhere. using (Stream stream = linker.Allocate(Runtime.Metadata.Symbol.Name, SectionKind.Text, module.Metadata.Metadata.Length, 0)) using (BinaryWriter bw = new BinaryWriter(stream, Encoding.ASCII)) { bw.Write(module.Metadata.Metadata); } }
/// <summary> /// Allocates the metadata stream in the output assembly. /// </summary> /// <param name="linker">The linker to allocate the metadata stream in.</param> /// <returns>The allocated metadata stream.</returns> private static Stream AllocateMetadataStream(IAssemblyLinker linker) { return(linker.Allocate(Symbol.Name, SectionKind.Text, 0, 0)); }
/// <summary> /// Requests a stream to emit native instructions to. /// </summary> /// <returns>A stream object, which can be used to store emitted instructions.</returns> public virtual Stream RequestCodeStream() { return(_linker.Allocate(_method, SectionKind.Text, 0, 0)); }
private void AllocateSpace(IAssemblyLinker linker, RuntimeField field, SectionKind section, int size, int alignment) { using (Stream stream = linker.Allocate (field, section, size, alignment)) { if (IntPtr.Zero != field.RVA) InitializeStaticValueFromRVA (stream, size, field); else WriteDummyBytes (stream, size); } }
/// <summary> /// Allocates the metadata stream in the output assembly. /// </summary> /// <param name="linker">The linker to allocate the metadata stream in.</param> /// <returns>The allocated metadata stream.</returns> private static Stream AllocateMetadataStream(IAssemblyLinker linker) { return linker.Allocate(Symbol.Name, SectionKind.Text, 0, 0); }
/// <summary> /// Requests a stream to emit native instructions to. /// </summary> /// <returns>A stream object, which can be used to store emitted instructions.</returns> public virtual Stream RequestCodeStream() { return(linker.Allocate(method.ToString(), SectionKind.Text, 0, 0)); }
/// <summary> /// Writes the multiboot _header. /// </summary> /// <param name="compiler">The assembly compiler.</param> /// <param name="linker">The linker.</param> /// <param name="entryPoint">The virtualAddress of the multiboot compliant entry point.</param> private void WriteMultibootHeader(AssemblyCompiler compiler, IAssemblyLinker linker, IntPtr entryPoint) { // HACK: According to the multiboot specification this _header must be within the first 8K of the // kernel binary. Since the text section is always first, this should take care of the problem. using (Stream stream = linker.Allocate(MultibootHeaderSymbolName, SectionKind.Text, 64, 4)) using (BinaryWriter bw = new BinaryWriter(stream, Encoding.ASCII)) { // flags - multiboot flags uint flags = /*HEADER_MB_FLAG_VIDEO_MODES_REQUIRED | */HEADER_MB_FLAG_MEMORY_INFO_REQUIRED | HEADER_MB_FLAG_MODULES_PAGE_ALIGNED; // The multiboot _header checksum uint csum = 0; // header_addr is the load virtualAddress of the multiboot _header uint header_addr = 0; // load_addr is the base virtualAddress of the binary in memory uint load_addr = 0; // load_end_addr holds the virtualAddress past the last byte to load From the image uint load_end_addr = 0; // bss_end_addr is the virtualAddress of the last byte to be zeroed out uint bss_end_addr = 0; // entry_point the load virtualAddress of the entry point to invoke uint entry_point = (uint)entryPoint.ToInt32(); // Are we linking an ELF binary? if (!(linker is Elf32Linker || linker is Elf64Linker)) { // Check the linker layout settings if (linker.LoadSectionAlignment != linker.VirtualSectionAlignment) throw new LinkerException(@"Load and virtual section alignment must be identical if you are booting non-ELF binaries with a multiboot bootloader."); // No, special multiboot treatment required flags |= HEADER_MB_FLAG_NON_ELF_BINARY; header_addr = (uint)(linker.GetSection(SectionKind.Text).VirtualAddress.ToInt64() + linker.GetSymbol(MultibootHeaderSymbolName).SectionAddress); load_addr = (uint)linker.BaseAddress; load_end_addr = 0; bss_end_addr = 0; } // Calculate the checksum csum = unchecked(0U - HEADER_MB_MAGIC - flags); bw.Write(HEADER_MB_MAGIC); bw.Write(flags); bw.Write(csum); bw.Write(header_addr); bw.Write(load_addr); bw.Write(load_end_addr); bw.Write(bss_end_addr); // HACK: Symbol has been hacked. What's the correct way to do this? linker.Link(LinkType.AbsoluteAddress | LinkType.I4, MultibootHeaderSymbolName, (int)stream.Position, 0, @"Mosa.Tools.Compiler.LinkerGenerated.<$>MultibootInit()", IntPtr.Zero); bw.Write(videoMode); bw.Write(videoWidth); bw.Write(videoHeight); bw.Write(videoDepth); } }