public void AddSourceInformation(LinkerSymbol baseSymbol, long offset, string information) { lock (mylock3) { source.Add(new Tuple <LinkerSymbol, long, string>(baseSymbol, offset, information)); } }
protected override unsafe void AddVmCalls(IDictionary <string, LinkerSymbol> virtualMachineCalls) { Trace.WriteLine(@"TestAssemblyLinker adding VM calls:"); IntPtr allocate = Marshal.GetFunctionPointerForDelegate(allocateArrayHandler); const string allocateArrayMethod = @"Mosa.Internal.Runtime.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.Remove(allocateArrayMethod); virtualMachineCalls.Add(allocateArrayMethod, symbol); IntPtr allocateObject = Marshal.GetFunctionPointerForDelegate(allocateObjectHandler); const string allocateObjectMethod = @"Mosa.Internal.Runtime.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.Remove(allocateObjectMethod); virtualMachineCalls.Add(allocateObjectMethod, symbol); }
protected override void Setup() { base.Setup(); symbol = MethodCompiler.Linker.GetSymbol(MethodCompiler.Method.FullName, SectionKind.Text); simLinker = MethodCompiler.Linker as SimLinker; }
public void AddTargetSymbol(LinkerSymbol baseSymbol, int offset, string name) { lock (mylock1) { targetSymbols.Add(new Tuple <LinkerSymbol, int, string>(baseSymbol, offset, name)); } }
public void AddInstruction(LinkerSymbol baseSymbol, long offset, SimInstruction instruction) { lock (mylock2) { instructions.Add(new Tuple <LinkerSymbol, long, SimInstruction>(baseSymbol, offset, instruction)); } }
public void ClearSymbolInformation(LinkerSymbol linkerSymbol) { lock (symbolData) { symbolData.Remove(linkerSymbol); } }
private string GetFinalSymboName(LinkerSymbol symbol) { if (symbol.ExternalSymbolName != null) { return(symbol.ExternalSymbolName); } if (symbol.SectionKind != SectionKind.Text) { return(symbol.Name); } if (!EmitShortSymbolName) { return(symbol.Name); } int pos = symbol.Name.LastIndexOf(") "); if (pos < 0) { return(symbol.Name); } var shortname = symbol.Name.Substring(0, pos + 1); return(shortname); }
protected override void Run() { if (multibootMethod == null) { multibootHeader = Linker.CreateSymbol(MultibootHeaderSymbolName, SectionKind.Text, 1, 0x30); multibootMethod = Compiler.CreateLinkerMethod("MultibootInit"); Linker.EntryPoint = Linker.GetSymbol(multibootMethod.FullName, SectionKind.Text); WriteMultibootHeader(); Linker.CreateSymbol(MultibootEAX, SectionKind.BSS, Architecture.NativeAlignment, Architecture.NativePointerSize); Linker.CreateSymbol(MultibootEBX, SectionKind.BSS, Architecture.NativeAlignment, Architecture.NativePointerSize); return; } var typeInitializerSchedulerStage = Compiler.PostCompilePipeline.FindFirst <TypeInitializerSchedulerStage>(); var ecx = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ECX); var eax = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX); var ebx = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBX); var ebp = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBP); var esp = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ESP); var multibootEax = Operand.CreateUnmanagedSymbolPointer(TypeSystem, MultibootEAX); var multibootEbx = Operand.CreateUnmanagedSymbolPointer(TypeSystem, MultibootEBX); var zero = Operand.CreateConstant(TypeSystem.BuiltIn.I4, 0); var stackTop = Operand.CreateConstant(TypeSystem.BuiltIn.I4, STACK_ADDRESS); var basicBlocks = new BasicBlocks(); var block = basicBlocks.CreateBlock(); basicBlocks.AddHeadBlock(block); var ctx = new Context(block); // Setup the stack and place the sentinel on the stack to indicate the start of the stack ctx.AppendInstruction(X86.Mov, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, esp, 0), stackTop); ctx.AppendInstruction(X86.Mov, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, ebp, 0), zero); // Place the multiboot address into a static field ctx.AppendInstruction(X86.Mov, ecx, multibootEax); ctx.AppendInstruction(X86.Mov, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, ecx, 0), eax); ctx.AppendInstruction(X86.Mov, ecx, multibootEbx); ctx.AppendInstruction(X86.Mov, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, ecx, 0), ebx); // call type initializer var entryPoint = Operand.CreateSymbolFromMethod(TypeSystem, typeInitializerSchedulerStage.TypeInitializerMethod); ctx.AppendInstruction(X86.Call, null, entryPoint); // should never get here ctx.AppendInstruction(X86.Ret); Compiler.CompileMethod(multibootMethod, basicBlocks, 0); }
protected override void RunPreCompile() { multibootHeader = Linker.CreateSymbol(MultibootHeaderSymbolName, SectionKind.Text, 1, 0x30); Linker.CreateSymbol(MultibootEAX, SectionKind.BSS, Architecture.NativeAlignment, Architecture.NativePointerSize); Linker.CreateSymbol(MultibootEBX, SectionKind.BSS, Architecture.NativeAlignment, Architecture.NativePointerSize); multibootMethod = Compiler.CreateLinkerMethod("MultibootInit"); Linker.EntryPoint = Linker.GetSymbol(multibootMethod.FullName, SectionKind.Text); }
protected override void Setup() { base.Setup(); symbol = MethodCompiler.Linker.GetSymbol(MethodCompiler.Method.FullName, SectionKind.Text); stage = MethodCompiler.Compiler.PostCompilePipeline.FindFirst <SimLinkerFinalizationStage>() as SimLinkerFinalizationStage; Debug.Assert(stage != null); stage.ClearSymbolInformation(symbol); }
protected override void RunPreCompile() { multibootHeader = Linker.CreateSymbol(MultibootHeaderSymbolName, SectionKind.Text, 1, 0x30); multibootMethod = Compiler.CreateLinkerMethod("MultibootInit"); Linker.CreateSymbol(MultibootEAX, SectionKind.BSS, Architecture.NativeAlignment, Architecture.NativePointerSize); Linker.CreateSymbol(MultibootEBX, SectionKind.BSS, Architecture.NativeAlignment, Architecture.NativePointerSize); var startUpType = TypeSystem.GetTypeByName("Mosa.Runtime", "StartUp"); var startUpMethod = startUpType.FindMethodByName("Stage1"); Compiler.PlugSystem.CreatePlug(multibootMethod, startUpMethod); }
private SymbolInfo GetSymbolInfo(LinkerSymbol linkerSymbol) { SymbolInfo symbolInfo = null; lock (symbolData) { if (!symbolData.TryGetValue(linkerSymbol, out symbolInfo)) { symbolInfo = new SymbolInfo(); symbolData.Add(linkerSymbol, symbolInfo); } } return(symbolInfo); }
/// <summary> /// Writes the multiboot header. /// </summary> /// <param name="entryPoint">The virtualAddress of the multiboot compliant entry point.</param> protected void WriteMultibootHeader(LinkerSymbol entryPoint) { // According to the multiboot specification this header must be within the first 8K of the kernel binary. Linker.SetFirst(multibootHeader); var writer = new BinaryWriter(multibootHeader.Stream, Encoding.ASCII); // flags - multiboot flags uint flags = HEADER_MB_FLAG_MEMORY_INFO_REQUIRED | HEADER_MB_FLAG_MODULES_PAGE_ALIGNED | (HasVideo ? HEADER_MB_FLAG_VIDEO_MODES_REQUIRED : 0); // magic writer.Write(HEADER_MB_MAGIC); // flags writer.Write(flags); // checksum writer.Write(unchecked (0U - HEADER_MB_MAGIC - flags)); // header_addr - load address of the multiboot header Linker.Link(LinkType.AbsoluteAddress, PatchType.I32, multibootHeader, (int)writer.BaseStream.Position, multibootHeader, 0); writer.Write(0); // load_addr - address of the binary in memory writer.Write(0); // load_end_addr - address past the last byte to load from the image writer.Write(0); // bss_end_addr - address of the last byte to be zeroed out writer.Write(0); // entry_addr - address of the entry point to invoke Linker.Link(LinkType.AbsoluteAddress, PatchType.I32, multibootHeader, (int)writer.BaseStream.Position, entryPoint, 0); writer.Write(0); // Write video settings if video has been specified, otherwise pad writer.Write(0); writer.Write(HasVideo ? Width : 0); writer.Write(HasVideo ? Height : 0); writer.Write(HasVideo ? Depth : 0); }
/// <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 override Stream Allocate(string name, SectionKind section, int size, int alignment) { LinkerStream stream = (LinkerStream)base.Allocate(name, section, size, alignment); try { VirtualMemoryStream vms = (VirtualMemoryStream)stream.BaseStream; LinkerSymbol symbol = this.GetSymbol(name); symbol.VirtualAddress = new IntPtr(vms.Base.ToInt64() + vms.Position); } catch { stream.Dispose(); throw; } return(stream); }
protected override void RunPreCompile() { multibootHeader = Linker.DefineSymbol(MultibootHeaderSymbolName, SectionKind.Text, 1, 0x30); Linker.DefineSymbol(MultibootEAX, SectionKind.BSS, Architecture.NativeAlignment, Architecture.NativePointerSize); Linker.DefineSymbol(MultibootEBX, SectionKind.BSS, Architecture.NativeAlignment, Architecture.NativePointerSize); multibootMethod = Compiler.CreateLinkerMethod("MultibootInit"); Linker.EntryPoint = Linker.GetSymbol(multibootMethod.FullName); MethodScanner.MethodInvoked(multibootMethod, multibootMethod); var startUpType = TypeSystem.GetTypeByName("Mosa.Runtime", "StartUp"); var initializeMethod = startUpType.FindMethodByName("Initialize"); MethodScanner.MethodInvoked(initializeMethod, multibootMethod); }
/// <summary> /// Emits all symbols emitted in the binary file. /// </summary> /// <param name="linker">The assembly linker.</param> private void EmitSymbols(IAssemblyLinker linker) { _writer.WriteLine("Offset Virtual Length Symbol"); foreach (LinkerSymbol symbol in linker.Symbols) { _writer.WriteLine("{0:x16} {1:x16} {2:x16} {3}", symbol.Offset, symbol.VirtualAddress.ToInt64(), symbol.Length, symbol.Name); } LinkerSymbol entryPoint = linker.EntryPoint; if (entryPoint != null) { _writer.WriteLine(); _writer.WriteLine("Entry point is {0}", entryPoint.Name); _writer.WriteLine("\tat offset {0:x16}", entryPoint.Offset); _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 override Stream Allocate(string name, SectionKind section, int size, int alignment) { LinkerStream stream = (LinkerStream)base.Allocate(name, section, size, alignment); try { VirtualMemoryStream vms = (VirtualMemoryStream)stream.BaseStream; LinkerSymbol symbol = GetSymbol(name); symbol.VirtualAddress = new IntPtr(vms.Base.ToInt64() + vms.Position); Trace.WriteLine("Symbol " + name + " located at 0x" + symbol.VirtualAddress.ToInt32().ToString("x08")); } catch { stream.Dispose(); throw; } return(stream); }
/// <summary> /// Performs stage specific processing on the compiler context. /// </summary> /// <param name="compiler">The compiler context to perform processing in.</param> public void Run(AssemblyCompiler compiler) { if (compiler == null) { throw new ArgumentNullException(@"compiler"); } IAssemblyLinker linker = compiler.Pipeline.Find <IAssemblyLinker>(); Debug.Assert(linker != null, @"No linker??"); _cliHeader.Cb = 0x48; _cliHeader.MajorRuntimeVersion = 2; _cliHeader.MinorRuntimeVersion = 0; _cliHeader.Flags = RuntimeImageFlags.ILOnly; _cliHeader.EntryPointToken = 0x06000001; // FIXME: ?? LinkerSymbol metadata = linker.GetSymbol(Mosa.Runtime.Metadata.Symbol.Name); _cliHeader.Metadata.VirtualAddress = (uint)(linker.GetSection(SectionKind.Text).VirtualAddress.ToInt64() + metadata.SectionAddress); _cliHeader.Metadata.Size = (int)metadata.Length; WriteCilHeader(compiler, linker); }
/// <summary> /// Allocates memory in the specified section. /// </summary> /// <param name="member">The metadata member to allocate space for.</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 override Stream Allocate(RuntimeMember member, SectionKind section, int size, int alignment) { string name = CreateSymbolName(member); LinkerStream stream = (LinkerStream)base.Allocate(name, section, size, alignment); try { VirtualMemoryStream vms = (VirtualMemoryStream)stream.BaseStream; // Save the member address member.Address = new IntPtr(vms.Base.ToInt64() + vms.Position); LinkerSymbol symbol = this.GetSymbol(name); symbol.VirtualAddress = member.Address; } catch { stream.Dispose(); throw; } return(stream); }
private void WriteArgument(EndianAwareBinaryWriter writer, LinkerSymbol symbol, MosaType type, object value) { if (type.IsEnum) { type = type.GetEnumUnderlyingType(); } switch (type.TypeCode) { // 1 byte case MosaTypeCode.Boolean: writer.Write((bool)value); break; case MosaTypeCode.U1: writer.Write((byte)value); break; case MosaTypeCode.I1: writer.Write((sbyte)value); break; // 2 bytes case MosaTypeCode.Char: writer.Write((char)value); break; case MosaTypeCode.U2: writer.Write((ushort)value); break; case MosaTypeCode.I2: writer.Write((short)value); break; // 4 bytes case MosaTypeCode.U4: writer.Write((uint)value); break; case MosaTypeCode.I4: writer.Write((int)value); break; case MosaTypeCode.R4: writer.Write((float)value); break; // 8 bytes case MosaTypeCode.U8: writer.Write((ulong)value); break; case MosaTypeCode.I8: writer.Write((long)value); break; case MosaTypeCode.R8: writer.Write((double)value); break; // SZArray case MosaTypeCode.SZArray: Debug.Assert(value is MosaCustomAttribute.Argument[]); var arr = (MosaCustomAttribute.Argument[])value; writer.Write(arr.Length, TypeLayout.NativePointerSize); foreach (var elem in arr) { WriteArgument(writer, symbol, elem.Type, elem.Value); } break; // String case MosaTypeCode.String: // Since strings are immutable, make it an object that we can just use var str = (string)value; Linker.Link(LinkType.AbsoluteAddress, NativePatchType, symbol, writer.Position, Metadata.TypeDefinition + "System.String", 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize * 2); writer.Write(str.Length, TypeLayout.NativePointerSize); writer.Write(System.Text.Encoding.Unicode.GetBytes(str)); break; default: if (type.FullName == "System.Type") { var valueType = (MosaType)value; Linker.Link(LinkType.AbsoluteAddress, NativePatchType, symbol, writer.Position, Metadata.TypeDefinition + valueType.FullName, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); } else { throw new NotSupportedException(); } break; } }
/// <summary> /// Writes the multiboot header. /// </summary> /// <param name="entryPoint">The virtualAddress of the multiboot compliant entry point.</param> private void WriteMultibootHeader() { // 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. LinkerSymbol entryPoint = Linker.EntryPoint; //entryPoint = Linker.GetSymbol(MultibootHeaderSymbolName, SectionKind.Text); var stream = multibootHeader.Stream; var writer = new BinaryWriter(stream, Encoding.ASCII); // flags - multiboot flags uint flags = HEADER_MB_FLAG_MEMORY_INFO_REQUIRED | HEADER_MB_FLAG_MODULES_PAGE_ALIGNED; if (HasVideo) { flags |= HEADER_MB_FLAG_VIDEO_MODES_REQUIRED; } uint load_addr = 0; // magic writer.Write(HEADER_MB_MAGIC); // flags writer.Write(flags); // checksum writer.Write(unchecked (0U - HEADER_MB_MAGIC - flags)); // header_addr - load address of the multiboot header Linker.Link(LinkType.AbsoluteAddress, PatchType.I4, multibootHeader, (int)stream.Position, 0, multibootHeader, 0); writer.Write(0); // load_addr - address of the binary in memory writer.Write(load_addr); // load_end_addr - address past the last byte to load from the image writer.Write(0); // bss_end_addr - address of the last byte to be zeroed out writer.Write(0); // entry_addr - address of the entry point to invoke Linker.Link(LinkType.AbsoluteAddress, PatchType.I4, multibootHeader, (int)stream.Position, 0, entryPoint, 0); writer.Write(0); // Write video settings if video has been specified, otherwise pad if (HasVideo) { writer.Write(0); // Mode, 0 = linear writer.Write(Width); // Width, 1280px writer.Write(Height); // Height, 720px writer.Write(Depth); // Depth, 24px } else { writer.Write(0); writer.Write(0); writer.Write(0); writer.Write(0); } }
private LinkerSymbol CreateTypeDefinition(MosaType type, LinkerSymbol assemblyTableSymbol) { // Emit type table var typeNameSymbol = EmitStringWithLength(Metadata.NameString + type.FullName, type.FullName); var typeTableSymbol = Linker.DefineSymbol(Metadata.TypeDefinition + type.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer = new EndianAwareBinaryWriter(typeTableSymbol.Stream, Architecture.Endianness); // 1. Pointer to Name Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, typeNameSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 2. Pointer to Custom Attributes if (type.CustomAttributes.Count > 0) { var customAttributeListSymbol = CreateCustomAttributesTable(type); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, customAttributeListSymbol, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 3. Type Code & Attributes writer.Write(((uint)type.TypeCode << 24) + (uint)type.TypeAttributes, TypeLayout.NativePointerSize); // 4. Size writer.Write((uint)TypeLayout.GetTypeSize(type), TypeLayout.NativePointerSize); // 5. Pointer to Assembly Definition Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, assemblyTableSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 6. Pointer to Base Type if (type.BaseType != null) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, Metadata.TypeDefinition + type.BaseType.FullName, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 7. Pointer to Declaring Type if (type.DeclaringType != null) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, Metadata.TypeDefinition + type.DeclaringType.FullName, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 8. Pointer to Element Type if (type.ElementType != null) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, Metadata.TypeDefinition + type.ElementType.FullName, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 9. Constructor that accepts no parameters, if any, for this type foreach (var method in type.Methods) { if (!method.IsConstructor || method.Signature.Parameters.Count != 0 || method.HasOpenGenericParams) { continue; } var targetMethodData = GetTargetMethodData(method); if (targetMethodData.HasCode) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, Metadata.MethodDefinition + targetMethodData.Method.FullName, 0); } break; } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 10. Properties (if any) if (type.Properties.Count > 0) { var propertiesSymbol = CreatePropertyDefinitions(type); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, propertiesSymbol, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); // If the type is not an interface continue, otherwise just pad until the end if (!type.IsInterface) { // 11. Fields (if any) if (type.Fields.Count > 0) { var fieldsSymbol = CreateFieldDefinitions(type); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, fieldsSymbol, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); var interfaces = type.HasOpenGenericParams ? null : GetInterfaces(type); // If the type doesn't use interfaces then skip 9 and 10 if (interfaces != null && interfaces.Count > 0) { // 12. Pointer to Interface Slots var interfaceSlotTableSymbol = CreateInterfaceSlotTable(type, interfaces); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, interfaceSlotTableSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); // 13. Pointer to Interface Bitmap var interfaceBitmapSymbol = CreateInterfaceBitmap(type, interfaces); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, interfaceBitmapSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); } else { // Fill 12 and 13 with zeros writer.WriteZeroBytes(TypeLayout.NativePointerSize * 2); } // For the next part we'll need to get the list of methods from the MosaTypeLayout var methodList = TypeLayout.GetMethodTable(type) ?? new List <MosaMethod>(); // 14. Number of Methods writer.Write(methodList.Count, TypeLayout.NativePointerSize); // 15. Pointer to Methods foreach (var method in methodList) { var targetMethodData = GetTargetMethodData(method); if (targetMethodData.HasCode) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, targetMethodData.Method.FullName, 0); } writer.WriteZeroBytes(TypeLayout.NativePointerSize); } // 16. Pointer to Method Definitions foreach (var method in methodList) { // Create definition and get the symbol var methodDefinitionSymbol = CreateMethodDefinition(method); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeTableSymbol, writer.Position, methodDefinitionSymbol, 0); writer.WriteZeroBytes(TypeLayout.NativePointerSize); } } else { // Fill 11, 12, 13, 14 with zeros, 15 & 16 can be left out. writer.WriteZeroBytes(TypeLayout.NativePointerSize * 4); } return(typeTableSymbol); }
private LinkerSymbol CreateTypeDefinition(MosaType type, LinkerSymbol assemblyTableSymbol) { // Emit type table var typeNameSymbol = EmitStringWithLength(Metadata.NameString + type.FullName, type.FullName); var typeDefinitionSymbol = Linker.DefineSymbol(Metadata.TypeDefinition + type.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0); var writer = new BinaryWriter(typeDefinitionSymbol.Stream); // 1. Pointer to Name Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), typeNameSymbol, (int)Compiler.ObjectHeaderSize); writer.WriteZeroBytes(NativePointerSize); // 2. Pointer to Custom Attributes if (type.CustomAttributes.Count > 0) { var customAttributeListSymbol = CreateCustomAttributesTable(type); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), customAttributeListSymbol, 0); } writer.WriteZeroBytes(NativePointerSize); // 3. Type Code & Attributes writer.Write(((uint)type.TypeCode << 24) + (uint)type.TypeAttributes, NativePointerSize); // 4. Size writer.Write((uint)TypeLayout.GetTypeSize(type), NativePointerSize); // 5. Pointer to Assembly Definition Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), assemblyTableSymbol, 0); writer.WriteZeroBytes(NativePointerSize); // 6. Pointer to Base Type if (type.BaseType != null) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), Metadata.TypeDefinition + type.BaseType.FullName, 0); } writer.WriteZeroBytes(NativePointerSize); // 7. Pointer to Declaring Type if (type.DeclaringType != null) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), Metadata.TypeDefinition + type.DeclaringType.FullName, 0); } writer.WriteZeroBytes(NativePointerSize); // 8. Pointer to Element Type if (type.ElementType != null) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), Metadata.TypeDefinition + type.ElementType.FullName, 0); } writer.WriteZeroBytes(NativePointerSize); // 9. Constructor that accepts no parameters, if any, for this type foreach (var method in type.Methods) { if (!method.IsConstructor || method.Signature.Parameters.Count != 0 || method.HasOpenGenericParams) { continue; } var targetMethodData = GetTargetMethodData(method); if (targetMethodData.HasCode) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), Metadata.MethodDefinition + targetMethodData.Method.FullName, 0); } break; } writer.WriteZeroBytes(NativePointerSize); // 10. Properties (if any) if (type.Properties.Count > 0) { var propertiesSymbol = CreatePropertyDefinitions(type); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), propertiesSymbol, 0); } writer.WriteZeroBytes(NativePointerSize); LinkerSymbol interfaceSlotTableSymbol = null; // 11. Fields Definitions if (!type.IsInterface && type.Fields.Count > 0) { var fieldsSymbol = CreateFieldDefinitions(type); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), fieldsSymbol, 0); } writer.WriteZeroBytes(NativePointerSize); var interfaces = type.IsInterface || type.HasOpenGenericParams ? null : GetInterfaces(type); if (interfaces != null && interfaces.Count == 0) { interfaces = null; } // 12. Pointer to Interface Slots if (interfaces != null) { interfaceSlotTableSymbol = CreateInterfaceSlotTable(type, interfaces); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), interfaceSlotTableSymbol, 0); } writer.WriteZeroBytes(NativePointerSize); // 13. Pointer to Interface Bitmap if (interfaces != null) { var interfaceBitmapSymbol = CreateInterfaceBitmap(type, interfaces); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), interfaceBitmapSymbol, 0); } writer.WriteZeroBytes(NativePointerSize); var methodList = TypeLayout.GetMethodTable(type); // 14. Number of Methods writer.Write(methodList == null ? 0 : methodList.Count, NativePointerSize); // 15. Method Table if (methodList != null) { foreach (var method in methodList) { var targetMethodData = GetTargetMethodData(method); if (targetMethodData.HasCode) { Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), targetMethodData.Method.FullName, 0); } writer.WriteZeroBytes(NativePointerSize); } } // 16. Method Definition Table if (!type.IsInterface && methodList != null) { foreach (var method in methodList) { // Create definition and get the symbol var methodDefinitionSymbol = CreateMethodDefinition(method); Linker.Link(LinkType.AbsoluteAddress, NativePatchType, typeDefinitionSymbol, writer.GetPosition(), methodDefinitionSymbol, 0); writer.WriteZeroBytes(NativePointerSize); } } return(typeDefinitionSymbol); }
/// <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) { try { Stream baseStream = Allocate(section, size, alignment); // 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 Stream result = new LinkerStream(symbol, baseStream, size); return result; } catch (ArgumentException argx) { throw new LinkerException(String.Format(@"Symbol {0} defined multiple times.", name), argx); } }
protected unsafe override void AddVmCalls(IDictionary<string, LinkerSymbol> virtualMachineCalls) { Trace.WriteLine(@"TestAssemblyLinker adding VM calls:"); IntPtr allocate = Marshal.GetFunctionPointerForDelegate(allocateArrayHandler); const string allocateArrayMethod = @"Mosa.Internal.Runtime.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.Remove(allocateArrayMethod); virtualMachineCalls.Add(allocateArrayMethod, symbol); IntPtr allocateObject = Marshal.GetFunctionPointerForDelegate(allocateObjectHandler); const string allocateObjectMethod = @"Mosa.Internal.Runtime.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.Remove(allocateObjectMethod); virtualMachineCalls.Add(allocateObjectMethod, symbol); }
public SymbolEntry(LinkerSymbol linkerSymbol, bool display32) { LinkerSymbol = linkerSymbol; this.display32 = display32; SectionKind = linkerSymbol.SectionKind.ToString(); }
public void AddTargetSymbol(LinkerSymbol baseSymbol, int offset, string name) { var symbolInfo = GetSymbolInfo(baseSymbol); symbolInfo.targetSymbols.Add(new Tuple <int, string>(offset, name)); }
public void AddInstruction(LinkerSymbol baseSymbol, long offset, SimInstruction instruction) { var symbolInfo = GetSymbolInfo(baseSymbol); symbolInfo.instructions.Add(new Tuple <long, SimInstruction>(offset, instruction)); }
public void AddSourceInformation(LinkerSymbol baseSymbol, long offset, string information) { var symbolInfo = GetSymbolInfo(baseSymbol); symbolInfo.source.Add(new Tuple <long, string>(offset, information)); }