/// <summary> /// Initializes a new instance of the <see cref="LinkerStream"/> class. /// </summary> /// <param name="symbol">The linker symbol created by this stream.</param> /// <param name="stream">The stream provided by the actual linker instance.</param> /// <param name="length">The length of the symbol. Set to zero, if length is unknown.</param> public LinkerStream(LinkerSymbol symbol, Stream stream, long length) { if (null == symbol) throw new ArgumentNullException(@"symbol"); if (null == stream) throw new ArgumentNullException(@"stream"); this.length = length; this.start = stream.Position; this.symbol = symbol; this.stream = stream; }
/// <summary> /// Releases the unmanaged resources used by the <see cref="T:System.IO.Stream"/> and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { if (this.stream != null && this.symbol != null) { // Fix the linker symbol size this.symbol.Length = this.Position; // Clear the stream & symbol this.stream = null; this.symbol = null; } base.Dispose(disposing); }
/// <summary> /// Initializes a new instance of the <see cref="LinkerStream"/> class. /// </summary> /// <param name="symbol">The linker symbol created by this stream.</param> /// <param name="stream">The stream provided by the actual linker instance.</param> /// <param name="length">The length of the symbol. Set to zero, if length is unknown.</param> public LinkerStream(LinkerSymbol symbol, Stream stream, long length) { if (null == symbol) { throw new ArgumentNullException("symbol"); } if (null == stream) { throw new ArgumentNullException("stream"); } this.length = length; this.start = stream.Position; this.symbol = symbol; this.stream = stream; }
/// <summary> /// Emits all symbols emitted in the binary file. /// </summary> /// <param name="linker">The assembly linker.</param> private void EmitSymbols(IAssemblyLinker linker) { this.writer.WriteLine("Offset Virtual Length Symbol"); foreach (LinkerSymbol symbol in linker.Symbols) { this.writer.WriteLine("{0:x16} {1:x16} {2:x16} {3}", symbol.Offset, symbol.VirtualAddress.ToInt64(), symbol.Length, symbol.Name); } LinkerSymbol entryPoint = linker.EntryPoint; if (null != entryPoint) { this.writer.WriteLine(); this.writer.WriteLine("Entry point is {0}", entryPoint.Name); this.writer.WriteLine("\tat offset {0:x16}", entryPoint.Offset); this.writer.WriteLine("\tat virtual address {0:x16}", entryPoint.VirtualAddress.ToInt64()); } }
/// <summary> /// Allocates a symbol of the given name in the specified section. /// </summary> /// <param name="name">The name of the symbol.</param> /// <param name="section">The executable section to allocate From.</param> /// <param name="size">The number of bytes to allocate. If zero, indicates an unknown amount of memory is required.</param> /// <param name="alignment">The alignment. A value of zero indicates the use of a default alignment for the section.</param> /// <returns> /// A stream, which can be used to populate the section. /// </returns> public virtual Stream Allocate(string name, SectionKind section, int size, int alignment) { Stream stream = Allocate(section, size, alignment); try { // Create a linker symbol for the name LinkerSymbol symbol = new LinkerSymbol(name, section, stream.Position); // Save the symbol for later use _symbols.Add(symbol.Name, symbol); // Wrap the stream to catch premature disposal stream = new LinkerStream(symbol, stream, size); } catch (ArgumentException argx) { throw new LinkerException(String.Format("Symbol {0} defined multiple times.", name), argx); } return(stream); }
/// <summary> /// Allocates a symbol of the given name in the specified section. /// </summary> /// <param name="name">The name of the symbol.</param> /// <param name="section">The executable section to allocate From.</param> /// <param name="size">The number of bytes to allocate. If zero, indicates an unknown amount of memory is required.</param> /// <param name="alignment">The alignment. A value of zero indicates the use of a default alignment for the section.</param> /// <returns> /// A stream, which can be used to populate the section. /// </returns> public virtual Stream Allocate(string name, SectionKind section, int size, int alignment) { Stream result; Stream baseStream = Allocate(section, size, alignment); try { // Create a linker symbol for the name LinkerSymbol symbol = new LinkerSymbol(name, section, baseStream.Position); // Save the symbol for later use _symbols.Add(symbol.Name, symbol); // Wrap the stream to catch premature disposal result = new LinkerStream(symbol, baseStream, size); } catch (ArgumentException argx) { throw new LinkerException(String.Format(@"Symbol {0} defined multiple times.", name), argx); } return result; }
protected unsafe override void AddVmCalls(IDictionary<string, LinkerSymbol> virtualMachineCalls) { Trace.WriteLine(@"TestAssemblyLinker adding VM calls:"); IntPtr allocate = Marshal.GetFunctionPointerForDelegate(this.allocateArrayHandler); const string allocateArrayMethod = @"Mosa.Runtime.RuntimeBase.AllocateArray(Ptr methodTable,U4 elementSize,U4 elements)"; long virtualAddress = allocate.ToInt64(); Trace.WriteLine(String.Format("\t{0} at 0x{1:x08}", allocateArrayMethod, virtualAddress)); LinkerSymbol symbol = new LinkerSymbol(allocateArrayMethod, SectionKind.Text, virtualAddress); symbol.VirtualAddress = new IntPtr(symbol.SectionAddress); virtualMachineCalls.Add(allocateArrayMethod, symbol); IntPtr allocateObject = Marshal.GetFunctionPointerForDelegate(this.allocateObjectHandler); const string allocateObjectMethod = @"Mosa.Runtime.RuntimeBase.AllocateObject(Ptr methodTable,U4 classSize)"; virtualAddress = allocateObject.ToInt64(); Trace.WriteLine(String.Format("\t{0} at 0x{1:x08}", allocateObjectMethod, virtualAddress)); symbol = new LinkerSymbol(allocateObjectMethod, SectionKind.Text, virtualAddress); symbol.VirtualAddress = new IntPtr(symbol.SectionAddress); virtualMachineCalls.Add(allocateObjectMethod, symbol); }