Exemple #1
0
        private LinkerSymbol CreateInterfaceMethodTable(MosaType type, MosaType interfaceType)
        {
            // Emit interface method table
            var interfaceMethodTableSymbol = Linker.DefineSymbol(Metadata.InterfaceMethodTable + type.FullName + "$" + interfaceType.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer = new EndianAwareBinaryWriter(interfaceMethodTableSymbol.Stream, Architecture.Endianness);

            var interfaceMethodTable = TypeLayout.GetInterfaceTable(type, interfaceType) ?? new MosaMethod[0];

            // 1. Number of Interface Methods
            writer.Write((uint)interfaceMethodTable.Length, TypeLayout.NativePointerSize);

            // 2. Pointer to Interface Type
            Linker.Link(LinkType.AbsoluteAddress, NativePatchType, interfaceMethodTableSymbol, writer.Position, Metadata.TypeDefinition + interfaceType.FullName, 0);
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 3. Pointers to Method Definitions
            foreach (var method in interfaceMethodTable)
            {
                // Create definition and get the symbol
                var methodDefinitionSymbol = CreateMethodDefinition(method);

                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, interfaceMethodTableSymbol, writer.Position, methodDefinitionSymbol, 0);
                writer.WriteZeroBytes(TypeLayout.NativePointerSize);
            }

            return(interfaceMethodTableSymbol);
        }
        private LinkerSymbol CreateCustomAttributeArgument(string symbolName, int count, string name, MosaCustomAttribute.Argument arg, bool isField)
        {
            string nameForSymbol = name ?? count.ToString();

            nameForSymbol = symbolName + ":" + nameForSymbol;
            var symbol  = Linker.DefineSymbol(Metadata.CustomAttributeArgument + nameForSymbol, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer1 = new EndianAwareBinaryWriter(symbol.Stream, Architecture.Endianness);

            // 1. Pointer to name (if named)
            if (name != null)
            {
                var nameSymbol = EmitStringWithLength(Metadata.NameString + nameForSymbol, name);
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, symbol, writer1.Position, nameSymbol, 0);
            }
            writer1.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 2. Is Argument A Field
            writer1.Write(isField, TypeLayout.NativePointerSize);

            // 3. Argument Type Pointer
            Linker.Link(LinkType.AbsoluteAddress, NativePatchType, symbol, writer1.Position, Metadata.TypeDefinition + arg.Type.FullName, 0);
            writer1.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 4. Argument Size
            writer1.Write(ComputeArgumentSize(arg.Type, arg.Value), TypeLayout.NativePointerSize);

            // 5. Argument Value
            WriteArgument(writer1, symbol, arg.Type, arg.Value);

            return(symbol);
        }
Exemple #3
0
        private LinkerSymbol CreateParameterDefinition(MosaParameter parameter)
        {
            // Emit parameter name
            var parameterNameSymbol = EmitStringWithLength(Metadata.NameString + parameter, parameter.FullName);

            // Emit parameter table
            var parameterTableSymbol = Linker.DefineSymbol(Metadata.MethodDefinition + parameter.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer = new EndianAwareBinaryWriter(parameterTableSymbol.Stream, Architecture.Endianness);

            // 1. Pointer to Name
            Linker.Link(LinkType.AbsoluteAddress, NativePatchType, parameterTableSymbol, writer.Position, parameterNameSymbol, 0);
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 2. Pointer to Custom Attributes
            if (parameter.CustomAttributes.Count > 0)
            {
                var customAttributeListSymbol = CreateCustomAttributesTable(parameter);
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, parameterTableSymbol, writer.Position, customAttributeListSymbol, 0);
            }
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 3. Attributes
            writer.Write((uint)parameter.ParameterAttributes, TypeLayout.NativePointerSize);

            // 4. Pointer to Parameter Type
            Linker.Link(LinkType.AbsoluteAddress, NativePatchType, parameterTableSymbol, writer.Position, Metadata.TypeDefinition + parameter.ParameterType.FullName, 0);
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            return(parameterTableSymbol);
        }
Exemple #4
0
        private LinkerSymbol CreateAssemblyDefinition(MosaModule module)
        {
            // Emit assembly name
            var assemblyNameSymbol = EmitStringWithLength(Metadata.NameString + module.Assembly, module.Assembly);

            // Emit assembly table
            var assemblyTableSymbol = Linker.DefineSymbol(Metadata.AssemblyDefinition + module.Assembly, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer = new EndianAwareBinaryWriter(assemblyTableSymbol.Stream, Architecture.Endianness);

            // 1. Pointer to Assembly Name
            Linker.Link(LinkType.AbsoluteAddress, NativePatchType, assemblyTableSymbol, writer.Position, assemblyNameSymbol, 0);
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 2. Pointer to Custom Attributes
            if (module.CustomAttributes.Count > 0)
            {
                var customAttributeListSymbol = CreateCustomAttributesTable(module);
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, assemblyTableSymbol, writer.Position, customAttributeListSymbol, 0);
            }
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 3. Attributes - IsReflectionOnly (32bit length)
            uint flags = 0x0;

            if (module.IsReflectionOnly)
            {
                flags |= 0x1;
            }
            writer.Write(flags, TypeLayout.NativePointerSize);

            // 4. Number of Types
            uint count = 0;

            writer.WriteZeroBytes(4);

            // 5. Pointers to Types
            foreach (var type in module.Types.Values)
            {
                if (type.IsModule)
                {
                    continue;
                }

                var typeTableSymbol = CreateTypeDefinition(type, assemblyTableSymbol);

                // Link
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, assemblyTableSymbol, writer.Position, typeTableSymbol, 0);
                writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                count++;
            }

            writer.Position = 3 * TypeLayout.NativePointerSize;
            writer.Write(count, TypeLayout.NativePointerSize);

            return(assemblyTableSymbol);
        }
Exemple #5
0
        private LinkerSymbol CreateCustomAttributesTable(MosaUnit unit)
        {
            var symbolName = Metadata.CustomAttributesTable + unit.FullName;

            var customAttributesTableSymbol = Linker.GetSymbol(symbolName);

            if (customAttributesTableSymbol.Size != 0)
            {
                return(customAttributesTableSymbol);
            }

            // Emit custom attributes table
            customAttributesTableSymbol = Linker.DefineSymbol(symbolName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer = new EndianAwareBinaryWriter(customAttributesTableSymbol.Stream, Architecture.Endianness);

            // 1. Number of Custom Attributes
            writer.Write(unit.CustomAttributes.Count, TypeLayout.NativePointerSize);

            // 2. Pointers to Custom Attributes
            for (int i = 0; i < unit.CustomAttributes.Count; i++)
            {
                // Get custom attribute
                var ca = unit.CustomAttributes[i];

                // Build definition
                var customAttributeTableSymbol = CreateCustomAttribute(unit, ca, i);

                // Link
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, customAttributesTableSymbol, writer.Position, customAttributeTableSymbol, 0);
                writer.WriteZeroBytes(TypeLayout.NativePointerSize);
            }

            return(customAttributesTableSymbol);
        }
Exemple #6
0
        protected void WriteSymbolSection(Section section)
        {
            Debug.Assert(section == symbolSection);

            // first entry is completely filled with zeros
            writer.WriteZeroBytes(SymbolEntry.GetEntrySize(linkerFormatType));

            uint count = 1;

            foreach (var symbol in linker.Symbols)
            {
                var symbolEntry = new SymbolEntry()
                {
                    Name                    = AddToStringTable(symbol.Name),
                    Value                   = symbol.VirtualAddress,
                    Size                    = symbol.Size,
                    SymbolBinding           = SymbolBinding.Global,
                    SymbolVisibility        = SymbolVisibility.Default,
                    SymbolType              = symbol.SectionKind == SectionKind.Text ? SymbolType.Function : SymbolType.Object,
                    SectionHeaderTableIndex = GetSection(symbol.SectionKind).Index
                };

                symbolEntry.Write(linkerFormatType, writer);
                symbolTableOffset.Add(symbol, count);

                count++;
            }

            section.Size = (uint)(count * SymbolEntry.GetEntrySize(linkerFormatType));
        }
        private LinkerSymbol CreateCustomAttributesTable(MosaUnit unit)
        {
            // Emit custom attributes table
            var customAttributesTableSymbol = Linker.CreateSymbol(unit.FullName + Metadata.CustomAttributesTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer1 = new EndianAwareBinaryWriter(customAttributesTableSymbol.Stream, Architecture.Endianness);

            // 1. Number of Custom Attributes
            writer1.Write(unit.CustomAttributes.Count, TypeLayout.NativePointerSize);

            // 2. Pointers to Custom Attributes
            // Create the definitions along the way
            for (int i = 0; i < unit.CustomAttributes.Count; i++)
            {
                // Get custom attribute
                var ca = unit.CustomAttributes[i];

                // Build definition
                var customAttributeTableSymbol = CreateCustomAttribute(unit, ca, i);

                // Link
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, customAttributesTableSymbol, (int)writer1.Position, 0, customAttributeTableSymbol, 0);
                writer1.WriteZeroBytes(TypeLayout.NativePointerSize);
            }

            // Return customAttributesTableSymbol for linker usage
            return(customAttributesTableSymbol);
        }
Exemple #8
0
        private void EmitProtectedRegionTable()
        {
            var trace = CreateTraceLog("Regions");

            var protectedRegionTableSymbol = MethodCompiler.Linker.DefineSymbol(Metadata.ProtectedRegionTable + MethodCompiler.Method.FullName, SectionKind.ROData, NativeAlignment, 0);
            var writer = new EndianAwareBinaryWriter(protectedRegionTableSymbol.Stream, Architecture.Endianness);

            int sectioncount = 0;

            // 1. Number of Regions (filled in later)
            writer.Write((uint)0);

            foreach (var region in MethodCompiler.ProtectedRegions)
            {
                var handler = (uint)MethodCompiler.GetPosition(region.Handler.HandlerStart);

                trace?.Log($"Handler: {region.Handler.TryStart.ToString("X4")} to {region.Handler.TryEnd.ToString("X4")} Handler: {region.Handler.HandlerStart.ToString("X4")} Offset: [{handler.ToString("X4")}]");

                var sections = new List <Tuple <int, int> >();

                foreach (var block in region.IncludedBlocks)
                {
                    // Check if block continues to exist
                    if (!BasicBlocks.Contains(block))
                    {
                        continue;
                    }

                    int start = MethodCompiler.GetPosition(block.Label);
                    int end   = MethodCompiler.GetPosition(block.Label + 0x0F000000);

                    trace?.Log($"   Block: {block} [{start.ToString()}-{end.ToString()}]");

                    AddSection(sections, start, end);
                }

                foreach (var s in sections)
                {
                    int start = s.Item1;
                    int end   = s.Item2;

                    sectioncount++;

                    var name = Metadata.ProtectedRegionTable + MethodCompiler.Method.FullName + "$" + sectioncount.ToString();
                    var protectedRegionDefinition = CreateProtectedRegionDefinition(name, (uint)start, (uint)end, handler, region.Handler.ExceptionHandlerType, region.Handler.Type);
                    MethodCompiler.Linker.Link(LinkType.AbsoluteAddress, NativePatchType, protectedRegionTableSymbol, writer.Position, protectedRegionDefinition, 0);
                    writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                    trace?.Log($"     Section: [{start.ToString()}-{end.ToString()}]");
                }
            }

            // 1. Number of Regions (now put the real number)
            writer.Position = 0;
            writer.Write(sectioncount);
        }
Exemple #9
0
        private LinkerSymbol CreateCustomAttribute(MosaUnit unit, MosaCustomAttribute ca, int position)
        {
            // Emit custom attribute list
            string name = unit.FullName + ">>" + position.ToString() + ":" + ca.Constructor.DeclaringType.Name;

            var customAttributeSymbol = Linker.DefineSymbol(Metadata.CustomAttribute + name, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer1 = new EndianAwareBinaryWriter(customAttributeSymbol.Stream, Architecture.Endianness);

            // 1. Pointer to Attribute Type
            Linker.Link(LinkType.AbsoluteAddress, NativePatchType, customAttributeSymbol, writer1.Position, Metadata.TypeDefinition + ca.Constructor.DeclaringType.FullName, 0);
            writer1.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 2. Pointer to Constructor Method Definition
            Linker.Link(LinkType.AbsoluteAddress, NativePatchType, customAttributeSymbol, writer1.Position, Metadata.MethodDefinition + ca.Constructor.FullName, 0);

            writer1.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 3. Number of Arguments (Both unnamed and named)
            writer1.Write((uint)(ca.Arguments.Length + ca.NamedArguments.Length), TypeLayout.NativePointerSize);

            // 4. Pointers to Custom Attribute Arguments (Both unnamed and named)
            for (int i = 0; i < ca.Arguments.Length; i++)
            {
                // Build definition
                var customAttributeArgumentSymbol = CreateCustomAttributeArgument(name, i, null, ca.Arguments[i], false);

                // Link
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, customAttributeSymbol, writer1.Position, customAttributeArgumentSymbol, 0);
                writer1.WriteZeroBytes(TypeLayout.NativePointerSize);
            }

            foreach (var namedArg in ca.NamedArguments)
            {
                // Build definition
                var customAttributeArgumentSymbol = CreateCustomAttributeArgument(name, 0, namedArg.Name, namedArg.Argument, namedArg.IsField);

                // Link
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, customAttributeSymbol, writer1.Position, customAttributeArgumentSymbol, 0);
                writer1.WriteZeroBytes(TypeLayout.NativePointerSize);
            }

            return(customAttributeSymbol);
        }
Exemple #10
0
        private LinkerSymbol EmitStringWithLength(string name, string value)
        {
            // Strings are now going to be embedded objects since they are immutable
            var symbol = Linker.DefineSymbol(name, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer = new EndianAwareBinaryWriter(symbol.Stream, Architecture.Endianness);

            Linker.Link(LinkType.AbsoluteAddress, NativePatchType, symbol, writer.Position, Metadata.TypeDefinition + "System.String", 0);
            writer.WriteZeroBytes(TypeLayout.NativePointerSize * 2);
            writer.Write(value.Length, TypeLayout.NativePointerSize);
            writer.Write(Encoding.Unicode.GetBytes(value));
            return(symbol);
        }
Exemple #11
0
        private void CreateDefinitionTables()
        {
            // Emit assembly list
            var assemblyListSymbol = Linker.DefineSymbol(Metadata.AssembliesTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer             = new EndianAwareBinaryWriter(assemblyListSymbol.Stream, Architecture.Endianness);

            // 1. Number of Assemblies
            writer.Write((uint)TypeSystem.Modules.Count, TypeLayout.NativePointerSize);

            // 2. Pointers to Assemblies
            foreach (var module in TypeSystem.Modules)
            {
                var assemblyTableSymbol = CreateAssemblyDefinition(module);

                // Link
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, assemblyListSymbol, writer.Position, assemblyTableSymbol, 0);
                writer.WriteZeroBytes(TypeLayout.NativePointerSize);
            }
        }
Exemple #12
0
        private void WriteSymbolSection(Section section, EndianAwareBinaryWriter writer)
        {
            Debug.Assert(section == symbolSection);

            // first entry is completely filled with zeros
            writer.WriteZeroBytes(SymbolEntry.GetEntrySize(linkerFormatType));

            uint count = 1;

            foreach (var symbol in linker.Symbols)
            {
                if (symbol.SectionKind == SectionKind.Unknown && symbol.LinkRequests.Count == 0)
                {
                    continue;
                }

                Debug.Assert(symbol.SectionKind != SectionKind.Unknown, "symbol.SectionKind != SectionKind.Unknown");

                if (!(symbol.IsExternalSymbol || linker.EmitAllSymbols))
                {
                    continue;
                }

                var symbolEntry = new SymbolEntry()
                {
                    Name                    = AddToStringTable(symbol.ExternalSymbolName ?? symbol.Name),
                    Value                   = symbol.VirtualAddress,
                    Size                    = symbol.Size,
                    SymbolBinding           = SymbolBinding.Global,
                    SymbolVisibility        = SymbolVisibility.Default,
                    SymbolType              = symbol.SectionKind == SectionKind.Text ? SymbolType.Function : SymbolType.Object,
                    SectionHeaderTableIndex = GetSection(symbol.SectionKind).Index
                };

                symbolEntry.Write(linkerFormatType, writer);
                symbolTableOffset.Add(symbol, count);

                count++;
            }

            section.Size = count * SymbolEntry.GetEntrySize(linkerFormatType);
        }
        private LinkerSymbol CreateInterfaceSlotTable(MosaType type)
        {
            // Emit interface slot table
            var interfaceSlotTableSymbol = Linker.CreateSymbol(type.FullName + Metadata.InterfaceSlotTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer1 = new EndianAwareBinaryWriter(interfaceSlotTableSymbol.Stream, Architecture.Endianness);

            var slots = new List <MosaType>(TypeLayout.Interfaces.Count);

            foreach (MosaType interfaceType in TypeLayout.Interfaces)
            {
                if (type.Interfaces.Contains(interfaceType))
                {
                    slots.Add(interfaceType);
                }
                else
                {
                    slots.Add(null);
                }
            }

            // 1. Number of Interface slots
            writer1.Write((uint)slots.Count, TypeLayout.NativePointerSize);

            // 2. Pointers to Interface Method Tables
            foreach (MosaType interfaceType in slots)
            {
                if (interfaceType != null)
                {
                    var interfaceMethodTableSymbol = CreateInterfaceMethodTable(type, interfaceType);

                    // Link
                    Linker.Link(LinkType.AbsoluteAddress, NativePatchType, interfaceSlotTableSymbol, (int)writer1.Position, 0, interfaceMethodTableSymbol, 0);
                }
                writer1.WriteZeroBytes(TypeLayout.NativePointerSize);
            }

            // Return interfaceSlotTableSymbol for linker usage
            return(interfaceSlotTableSymbol);
        }
Exemple #14
0
        private LinkerSymbol CreateProtectedRegionDefinition(string name, uint start, uint end, uint handler, ExceptionHandlerType handlerType, MosaType exceptionType)
        {
            // Emit parameter table
            var protectedRegionDefinitionSymbol = MethodCompiler.Linker.DefineSymbol(name, SectionKind.ROData, 0 /*TypeLayout.NativePointerAlignment*/, 0);
            var writer1 = new EndianAwareBinaryWriter(protectedRegionDefinitionSymbol.Stream, Architecture.Endianness);

            // 1. Offset to start
            writer1.Write(start, TypeLayout.NativePointerSize);

            // 2. Offset to end
            writer1.Write(end, TypeLayout.NativePointerSize);

            // 3. Offset to handler
            writer1.Write(handler, TypeLayout.NativePointerSize);

            // 4. Handler type
            writer1.Write((uint)handlerType, TypeLayout.NativePointerSize);

            // 5. Exception object type
            if (handlerType == ExceptionHandlerType.Exception)
            {
                // Store method table pointer of the exception object type
                // The VES exception runtime will uses this to compare exception object types
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, protectedRegionDefinitionSymbol, writer1.Position, Metadata.TypeDefinition + exceptionType.FullName, 0);
            }
            else if (handlerType == ExceptionHandlerType.Filter)
            {
                // TODO: There are no plans in the short term to support filtered exception clause as C# does not use them
            }
            else
            {
            }

            writer1.WriteZeroBytes(TypeLayout.NativePointerSize);

            // Return protectedRegionSymbol for linker usage
            return(protectedRegionDefinitionSymbol);
        }
        protected void CreateMethodExceptionLookupTable()
        {
            // Emit assembly list
            var methodLookupTable = Linker.CreateSymbol(Metadata.MethodExceptionLookupTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer            = new EndianAwareBinaryWriter(methodLookupTable.Stream, Architecture.Endianness);

            // 1. Number of methods
            int count = 0;

            foreach (var module in TypeSystem.Modules)
            {
                foreach (var type in module.Types.Values)
                {
                    if (type.IsModule)
                    {
                        continue;
                    }

                    var methodList = TypeLayout.GetMethodTable(type);

                    if (methodList == null)
                    {
                        continue;
                    }

                    foreach (var method in methodList)
                    {
                        if (method.IsAbstract)
                        {
                            continue;
                        }

                        if (method.ExceptionHandlers.Count == 0)
                        {
                            continue;
                        }

                        count++;
                    }
                }
            }
            writer.Write(count);

            foreach (var module in TypeSystem.Modules)
            {
                foreach (var type in module.Types.Values)
                {
                    if (type.IsModule)
                    {
                        continue;
                    }

                    var methodList = TypeLayout.GetMethodTable(type);

                    if (methodList == null)
                    {
                        continue;
                    }

                    foreach (var method in methodList)
                    {
                        if (method.IsAbstract)
                        {
                            continue;
                        }

                        if (method.ExceptionHandlers.Count == 0)
                        {
                            continue;
                        }

                        // 1. Pointer to Method
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, (int)writer.Position, 0, method.FullName, SectionKind.Text, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                        // 2. Size of Method
                        Linker.Link(LinkType.Size, NativePatchType, methodLookupTable, (int)writer.Position, 0, method.FullName, SectionKind.Text, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                        // 3. Pointer to Method Definition
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, (int)writer.Position, 0, method.FullName + Metadata.MethodDefinition, SectionKind.ROData, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);
                    }
                }
            }
        }
        protected void CreateMethodExceptionLookupTable()
        {
            // Emit assembly list
            var methodLookupTable = Linker.DefineSymbol(Metadata.MethodExceptionLookupTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer            = new EndianAwareBinaryWriter(methodLookupTable.Stream, Architecture.Endianness);

            // 1. Number of methods
            int count = 0;

            writer.Write((int)0);

            foreach (var module in TypeSystem.Modules)
            {
                foreach (var type in module.Types.Values)
                {
                    if (type.IsModule)
                    {
                        continue;
                    }

                    if (!Compiler.MethodScanner.IsTypeAllocated(type))
                    {
                        continue;
                    }

                    var methodList = TypeLayout.GetMethodTable(type);

                    if (methodList == null)
                    {
                        continue;
                    }

                    foreach (var method in methodList)
                    {
                        if ((!method.HasImplementation && method.IsAbstract) || method.HasOpenGenericParams || method.DeclaringType.HasOpenGenericParams)
                        {
                            continue;
                        }

                        if (method.ExceptionHandlers.Count == 0)
                        {
                            continue;
                        }

                        if (!Compiler.MethodScanner.IsMethodInvoked(method))
                        {
                            continue;
                        }

                        // 1. Pointer to Method
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, writer.Position, method.FullName, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                        // 2. Size of Method
                        Linker.Link(LinkType.Size, NativePatchType, methodLookupTable, writer.Position, method.FullName, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                        // 3. Pointer to Method Definition
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodLookupTable, writer.Position, Metadata.MethodDefinition + method.FullName, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                        count++;
                    }
                }
            }

            writer.Position = 0;
            writer.Write(count);

            // emit null entry (FUTURE)
            //writer.WriteZeroBytes(TypeLayout.NativePointerSize * 3);
        }
Exemple #17
0
        private LinkerSymbol CreateMethodDefinition(MosaMethod method)
        {
            var symbolName        = Metadata.MethodDefinition + method.FullName;
            var methodTableSymbol = Linker.GetSymbol(symbolName);

            if (methodTableSymbol.Size != 0)
            {
                return(methodTableSymbol);
            }

            // Emit method name
            var methodNameSymbol = EmitStringWithLength(Metadata.NameString + method.FullName, method.FullName);

            // Emit method table
            methodTableSymbol = Linker.DefineSymbol(symbolName, SectionKind.ROData, TypeLayout.NativePointerAlignment, (method.Signature.Parameters.Count + 9) * TypeLayout.NativePointerSize);
            var writer = new EndianAwareBinaryWriter(methodTableSymbol.Stream, Architecture.Endianness);

            // 1. Pointer to Name
            Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, methodNameSymbol, 0);
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 2. Pointer to Custom Attributes
            if (method.CustomAttributes.Count > 0)
            {
                var customAttributeListSymbol = CreateCustomAttributesTable(method);
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, customAttributeListSymbol, 0);
            }
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 3. Attributes
            writer.Write((uint)method.MethodAttributes, TypeLayout.NativePointerSize);

            var targetMethodData = GetTargetMethodData(method);

            // 4. Local Stack Size (16 Bits) && Parameter Stack Size (16 Bits)
            writer.Write(targetMethodData.LocalMethodStackSize | (targetMethodData.ParameterStackSize << 16), TypeLayout.NativePointerSize);

            // 5. Pointer to Method
            if (targetMethodData.HasCode)
            {
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, targetMethodData.Method.FullName, 0);
            }
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 6. Pointer to return type
            Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, Metadata.TypeDefinition + method.Signature.ReturnType.FullName, 0);
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 7. Pointer to Exception Handler Table
            if (targetMethodData.HasProtectedRegions && targetMethodData.HasCode)
            {
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, Metadata.ProtectedRegionTable + targetMethodData.Method.FullName, 0);
            }
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 8. Pointer to GC Tracking information
            // TODO: This has yet to be designed.
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 9. Number of Parameters
            writer.Write((uint)method.Signature.Parameters.Count, TypeLayout.NativePointerSize);

            // 10. Pointers to Parameter Definitions
            foreach (var parameter in method.Signature.Parameters)
            {
                // Create definition and get the symbol
                var parameterDefinitionSymbol = CreateParameterDefinition(parameter);

                // Link
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, parameterDefinitionSymbol, 0);
                writer.WriteZeroBytes(TypeLayout.NativePointerSize);
            }

            return(methodTableSymbol);
        }
Exemple #18
0
        private LinkerSymbol CreatePropertyDefinitions(MosaType type)
        {
            // Emit properties table
            var propertiesTableSymbol = Linker.DefineSymbol(Metadata.PropertiesTable + type.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer = new EndianAwareBinaryWriter(propertiesTableSymbol.Stream, Architecture.Endianness);

            // 1. Number of Properties
            writer.Write((uint)type.Properties.Count, TypeLayout.NativePointerSize);

            // 2. Pointers to Property Definitions
            foreach (var property in type.Properties)
            {
                // Emit field name
                var fieldNameSymbol = EmitStringWithLength(Metadata.NameString + property.FullName, property.Name);

                // Emit property definition
                var propertyDefSymbol = Linker.DefineSymbol(Metadata.PropertyDefinition + property.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
                var writer2           = new EndianAwareBinaryWriter(propertyDefSymbol.Stream, Architecture.Endianness);

                // 1. Name
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, writer2.Position, fieldNameSymbol, 0);
                writer2.WriteZeroBytes(TypeLayout.NativePointerSize);

                // 2. Pointer to Custom Attributes
                if (property.CustomAttributes.Count > 0)
                {
                    var customAttributesTableSymbol = CreateCustomAttributesTable(property);
                    Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, writer.Position, customAttributesTableSymbol, 0);
                }
                writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                // 3. Attributes
                writer.Write((uint)property.PropertyAttributes, TypeLayout.NativePointerSize);

                // 4. Pointer to Property Type
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, writer2.Position, Metadata.TypeDefinition + property.PropertyType.FullName, 0);
                writer2.WriteZeroBytes(TypeLayout.NativePointerSize);

                // If the type is a interface then skip linking the methods
                if (!type.IsInterface)
                {
                    // TODO: Replace .HasImpelement with .HasCode

                    // 5. Pointer to Getter Method Definition
                    if (property.GetterMethod != null && property.GetterMethod.HasImplementation && !property.GetterMethod.HasOpenGenericParams)
                    {
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, writer2.Position, Metadata.MethodDefinition + property.GetterMethod.FullName, 0);
                    }
                    writer2.WriteZeroBytes(TypeLayout.NativePointerSize);

                    // 6. Pointer to Setter Method Definition
                    if (property.SetterMethod != null && property.SetterMethod.HasImplementation && !property.SetterMethod.HasOpenGenericParams)
                    {
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, writer2.Position, Metadata.MethodDefinition + property.SetterMethod.FullName, 0);
                    }
                    writer2.WriteZeroBytes(TypeLayout.NativePointerSize);
                }
                else
                {
                    // Fill 5 and 6 with zeros.
                    writer.WriteZeroBytes(TypeLayout.NativePointerSize * 2);
                }

                // Add pointer to properties table
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertiesTableSymbol, writer.Position, propertyDefSymbol, 0);
                writer.WriteZeroBytes(TypeLayout.NativePointerSize);
            }

            return(propertiesTableSymbol);
        }
Exemple #19
0
        private LinkerSymbol CreateFieldDefinitions(MosaType type)
        {
            // Emit fields table
            var fieldsTableSymbol = Linker.DefineSymbol(Metadata.FieldsTable + type.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer1           = new EndianAwareBinaryWriter(fieldsTableSymbol.Stream, Architecture.Endianness);

            // 1. Number of Fields
            writer1.Write((uint)type.Fields.Count, TypeLayout.NativePointerSize);

            // 2. Pointers to Field Definitions
            foreach (var field in type.Fields)
            {
                // Emit field name
                var fieldNameSymbol = EmitStringWithLength(Metadata.NameString + field.FullName, field.Name);

                // Emit field definition
                var fieldDefSymbol = Linker.DefineSymbol(Metadata.FieldDefinition + field.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
                var writer2        = new EndianAwareBinaryWriter(fieldDefSymbol.Stream, Architecture.Endianness);

                // 1. Name
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldDefSymbol, writer2.Position, fieldNameSymbol, 0);
                writer2.WriteZeroBytes(TypeLayout.NativePointerSize);

                // 2. Pointer to Custom Attributes
                if (field.CustomAttributes.Count > 0)
                {
                    var customAttributesTableSymbol = CreateCustomAttributesTable(field);
                    Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldDefSymbol, writer2.Position, customAttributesTableSymbol, 0);
                }
                writer2.WriteZeroBytes(TypeLayout.NativePointerSize);

                // 3. Attributes
                writer2.Write((uint)field.FieldAttributes, TypeLayout.NativePointerSize);

                // 4. Pointer to Field Type
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldDefSymbol, writer2.Position, Metadata.TypeDefinition + field.FieldType.FullName, 0);
                writer2.WriteZeroBytes(TypeLayout.NativePointerSize);

                // 5 & 6. Offset / Address + Size
                if (field.IsStatic && !field.IsLiteral && !type.HasOpenGenericParams)
                {
                    if (Compiler.MethodScanner.IsFieldAccessed(field))
                    {
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldDefSymbol, writer2.Position, field.FullName, 0);
                    }
                    writer2.WriteZeroBytes(TypeLayout.NativePointerSize);
                    writer2.Write(field.Data?.Length ?? 0, TypeLayout.NativePointerSize);
                }
                else
                {
                    writer2.WriteZeroBytes(TypeLayout.NativePointerSize);
                    writer2.Write(TypeLayout.GetFieldOffset(field), TypeLayout.NativePointerSize);
                }

                // Add pointer to field list
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldsTableSymbol, writer1.Position, fieldDefSymbol, 0);
                writer1.WriteZeroBytes(TypeLayout.NativePointerSize);
            }

            return(fieldsTableSymbol);
        }
        private LinkerSymbol CreateMethodDefinition(MosaMethod method)
        {
            // Emit method name
            var methodNameSymbol = EmitStringWithLength(method.FullName + Metadata.NameString, method.FullName);

            // Emit method table
            var methodTableSymbol = Linker.CreateSymbol(method.FullName + Metadata.MethodDefinition, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer1           = new EndianAwareBinaryWriter(methodTableSymbol.Stream, Architecture.Endianness);

            // 1. Pointer to Name
            Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, 0, methodNameSymbol, 0);
            writer1.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 2. Pointer to Custom Attributes
            if (method.CustomAttributes.Count > 0)
            {
                var customAttributeListSymbol = CreateCustomAttributesTable(method);
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, 0, customAttributeListSymbol, 0);
            }
            writer1.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 3. Attributes
            writer1.Write((uint)method.MethodAttributes, TypeLayout.NativePointerSize);

            // 4. Local Stack Size (16 Bits) && Parameter Stack Size (16 Bits)
            int value = TypeLayout.GetMethodStackSize(method) | (TypeLayout.GetMethodParameterStackSize(method) << 16);

            writer1.Write(value, TypeLayout.NativePointerSize);

            // 5. Pointer to Method
            if (!method.IsAbstract)
            {
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, 0, method.FullName, SectionKind.Text, 0);
            }
            writer1.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 6. Pointer to return type
            Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, 0, method.Signature.ReturnType.FullName + Metadata.TypeDefinition, SectionKind.ROData, 0);
            writer1.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 7. Pointer to Exception Handler Table
            if (method.ExceptionHandlers.Count != 0)
            {
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, 0, method.FullName + Metadata.ProtectedRegionTable, SectionKind.ROData, 0);
            }
            writer1.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 8. Pointer to GC Tracking information
            // TODO: This has yet to be designed.
            writer1.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 9. Number of Parameters
            writer1.Write((uint)method.Signature.Parameters.Count, TypeLayout.NativePointerSize);

            // 10. Pointers to Parameter Definitions
            foreach (var parameter in method.Signature.Parameters)
            {
                // Create definition and get the symbol
                var parameterDefinitionSymbol = CreateParameterDefinition(parameter);

                // Link
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, (int)writer1.Position, 0, parameterDefinitionSymbol, 0);
                writer1.WriteZeroBytes(TypeLayout.NativePointerSize);
            }

            // Return methodTableSymbol for linker usage
            return(methodTableSymbol);
        }
Exemple #21
0
        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;
            }
        }
Exemple #22
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);
        }
Exemple #23
0
        protected void CreateMethodExceptionLookupTable()
        {
            // Emit assembly list
            var exceptionMethodLookupTable = Linker.DefineSymbol(Metadata.MethodExceptionLookupTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer = new EndianAwareBinaryWriter(exceptionMethodLookupTable.Stream, Architecture.Endianness);

            // 1. Number of methods
            int count = 0;

            writer.Write((int)0);

            foreach (var module in TypeSystem.Modules)
            {
                foreach (var type in module.Types.Values)
                {
                    if (type.IsModule)
                    {
                        continue;
                    }

                    if (!Compiler.MethodScanner.IsTypeAllocated(type))
                    {
                        continue;
                    }

                    var methodList = TypeLayout.GetMethodTable(type);

                    if (methodList == null)
                    {
                        continue;
                    }

                    foreach (var method in methodList)
                    {
                        var targetMethodData = GetTargetMethodData(method);

                        if (!targetMethodData.HasCode)
                        {
                            continue;
                        }

                        if (!targetMethodData.HasProtectedRegions)
                        {
                            continue;
                        }

                        // 1. Pointer to Method
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, exceptionMethodLookupTable, writer.Position, targetMethodData.Method.FullName, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                        // 2. Size of Method
                        Linker.Link(LinkType.Size, NativePatchType, exceptionMethodLookupTable, writer.Position, targetMethodData.Method.FullName, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                        // 3. Pointer to Method Definition
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, exceptionMethodLookupTable, writer.Position, Metadata.MethodDefinition + method.FullName, 0);
                        writer.WriteZeroBytes(TypeLayout.NativePointerSize);

                        count++;
                    }
                }
            }

            writer.Position = 0;
            writer.Write(count);

            // emit null entry (FUTURE)
            //writer.WriteZeroBytes(TypeLayout.NativePointerSize * 3);
        }
        private LinkerSymbol CreateAssemblyDefinition(MosaModule module)
        {
            // Emit assembly name
            var assemblyNameSymbol = EmitStringWithLength(module.Assembly + Metadata.NameString, module.Assembly);

            // Emit assembly table
            var assemblyTableSymbol = Linker.CreateSymbol(module.Assembly + Metadata.AssemblyDefinition, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer1             = new EndianAwareBinaryWriter(assemblyTableSymbol.Stream, Architecture.Endianness);

            // 1. Pointer to Assembly Name
            Linker.Link(LinkType.AbsoluteAddress, NativePatchType, assemblyTableSymbol, (int)writer1.Position, 0, assemblyNameSymbol, 0);
            writer1.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 2. Pointer to Custom Attributes
            if (module.CustomAttributes.Count > 0)
            {
                var customAttributeListSymbol = CreateCustomAttributesTable(module);
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, assemblyTableSymbol, (int)writer1.Position, 0, customAttributeListSymbol, 0);
            }
            writer1.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 3. Attributes - IsReflectionOnly (32bit length)
            uint flags = 0x0;

            if (module.IsReflectionOnly)
            {
                flags |= 0x1;
            }
            writer1.Write(flags, TypeLayout.NativePointerSize);

            // 4. Number of Types
            uint count = 0;

            foreach (var type in module.Types.Values)
            {
                if (type.IsModule)
                {
                    continue;
                }

                count++;
            }
            writer1.Write(count, TypeLayout.NativePointerSize);

            // 5. Pointers to Types
            // Create the definitions along the way
            foreach (var type in module.Types.Values)
            {
                if (type.IsModule)
                {
                    continue;
                }

                // Run the type through the TypeLayout system
                //TypeLayout.ResolveType(type);

                var typeTableSymbol = CreateTypeDefinition(type, assemblyTableSymbol);

                // Link
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, assemblyTableSymbol, (int)writer1.Position, 0, typeTableSymbol, 0);
                writer1.WriteZeroBytes(TypeLayout.NativePointerSize);
            }

            // Return assemblyTableSymbol
            return(assemblyTableSymbol);
        }
        private LinkerSymbol CreateFieldDefinitions(MosaType type)
        {
            // Emit fields table
            var fieldsTableSymbol = Linker.CreateSymbol(type.FullName + Metadata.FieldsTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer1           = new EndianAwareBinaryWriter(fieldsTableSymbol.Stream, Architecture.Endianness);

            // 1. Number of Fields
            writer1.Write((uint)type.Fields.Count, TypeLayout.NativePointerSize);

            // 2. Pointers to Field Definitions
            foreach (MosaField field in type.Fields)
            {
                // Emit field name
                var fieldNameSymbol = EmitStringWithLength(field.FullName + Metadata.NameString, field.Name);

                // Emit field definition
                var fieldDefSymbol = Linker.CreateSymbol(field.FullName + Metadata.FieldDefinition, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
                var writer2        = new EndianAwareBinaryWriter(fieldDefSymbol.Stream, Architecture.Endianness);

                // 1. Name
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldDefSymbol, (int)writer2.Position, 0, fieldNameSymbol, 0);
                writer2.WriteZeroBytes(TypeLayout.NativePointerSize);

                // 2. Pointer to Custom Attributes
                if (field.CustomAttributes.Count > 0)
                {
                    var customAttributesTableSymbol = CreateCustomAttributesTable(field);
                    Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldDefSymbol, (int)writer2.Position, 0, customAttributesTableSymbol, 0);
                }
                writer2.WriteZeroBytes(TypeLayout.NativePointerSize);

                // 3. Attributes
                writer2.Write((uint)field.FieldAttributes, TypeLayout.NativePointerSize);

                // 4. Pointer to Field Type
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldDefSymbol, (int)writer2.Position, 0, field.FieldType.FullName + Metadata.TypeDefinition, SectionKind.ROData, 0);
                writer2.WriteZeroBytes(TypeLayout.NativePointerSize);

                // 5 & 6. Offset / Address + Size
                if (field.IsStatic && !field.IsLiteral)
                {
                    var section = (field.Data != null) ? SectionKind.ROData : SectionKind.BSS;
                    Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldDefSymbol, (int)writer2.Position, 0, field.FullName, section, 0);
                    writer2.WriteZeroBytes(TypeLayout.NativePointerSize);
                    writer2.Write((field.Data != null) ? field.Data.Length : 0, TypeLayout.NativePointerSize);
                }
                else
                {
                    writer2.WriteZeroBytes(TypeLayout.NativePointerSize);
                    writer2.Write(TypeLayout.GetFieldOffset(field), TypeLayout.NativePointerSize);
                }

                // Create another symbol with field data if any
                if (field.IsStatic)
                {
                    // Assign a memory slot to the static & initialize it, if there's initial data set
                    // Determine the size of the type & alignment requirements
                    int size, alignment;
                    Architecture.GetTypeRequirements(TypeLayout, field.FieldType, out size, out alignment);

                    size = TypeLayout.GetFieldSize(field);

                    // The linker section to move this field into
                    SectionKind section = field.Data != null ? section = SectionKind.ROData : section = SectionKind.BSS;

                    var symbol = Compiler.Linker.CreateSymbol(field.FullName, section, alignment, size);

                    if (field.Data != null)
                    {
                        symbol.Stream.Write(field.Data, 0, size);
                    }
                }

                // Add pointer to field list
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, fieldsTableSymbol, (int)writer1.Position, 0, fieldDefSymbol, 0);
                writer1.WriteZeroBytes(TypeLayout.NativePointerSize);
            }

            // Return fieldsTableSymbol for linker usage
            return(fieldsTableSymbol);
        }
Exemple #26
0
        private LinkerSymbol CreateMethodDefinition(MosaMethod method)
        {
            // Emit method name
            var methodNameSymbol = EmitStringWithLength(Metadata.NameString + method.FullName, method.FullName);

            // Emit method table
            var methodTableSymbol = Linker.DefineSymbol(Metadata.MethodDefinition + method.FullName, SectionKind.ROData, TypeLayout.NativePointerAlignment, (method.Signature.Parameters.Count + 9) * TypeLayout.NativePointerSize);
            var writer            = new EndianAwareBinaryWriter(methodTableSymbol.Stream, Architecture.Endianness);

            // 1. Pointer to Name
            Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, methodNameSymbol, 0);
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 2. Pointer to Custom Attributes
            if (method.CustomAttributes.Count > 0)
            {
                var customAttributeListSymbol = CreateCustomAttributesTable(method);
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, customAttributeListSymbol, 0);
            }
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 3. Attributes
            writer.Write((uint)method.MethodAttributes, TypeLayout.NativePointerSize);

            // 4. Local Stack Size (16 Bits) && Parameter Stack Size (16 Bits)
            var methodData = Compiler.CompilerData.GetMethodData(method);
            int value      = methodData.LocalMethodStackSize | (methodData.ParameterStackSize << 16);

            writer.Write(value, TypeLayout.NativePointerSize);

            // 5. Pointer to Method
            if (method.HasImplementation && !method.HasOpenGenericParams && !method.DeclaringType.HasOpenGenericParams /*&& !methodData.Inlined*/)              // TODO: Inline
            {
                if (Compiler.MethodScanner.IsMethodInvoked(method))
                {
                    Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, GetMethodNameConsiderPlug(method), 0);
                }
            }
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 6. Pointer to return type
            Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, Metadata.TypeDefinition + method.Signature.ReturnType.FullName, 0);
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 7. Pointer to Exception Handler Table
            if (method.ExceptionHandlers.Count != 0 && Compiler.MethodScanner.IsMethodInvoked(method))
            {
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, Metadata.ProtectedRegionTable + method.FullName, 0);
            }
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 8. Pointer to GC Tracking information
            // TODO: This has yet to be designed.
            writer.WriteZeroBytes(TypeLayout.NativePointerSize);

            // 9. Number of Parameters
            writer.Write((uint)method.Signature.Parameters.Count, TypeLayout.NativePointerSize);

            // 10. Pointers to Parameter Definitions
            foreach (var parameter in method.Signature.Parameters)
            {
                // Create definition and get the symbol
                var parameterDefinitionSymbol = CreateParameterDefinition(parameter);

                // Link
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, methodTableSymbol, writer.Position, parameterDefinitionSymbol, 0);
                writer.WriteZeroBytes(TypeLayout.NativePointerSize);
            }

            return(methodTableSymbol);
        }
        private LinkerSymbol CreatePropertyDefinitions(MosaType type)
        {
            // Emit properties table
            var propertiesTableSymbol = Linker.CreateSymbol(type.FullName + Metadata.PropertiesTable, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
            var writer1 = new EndianAwareBinaryWriter(propertiesTableSymbol.Stream, Architecture.Endianness);

            // 1. Number of Properties
            writer1.Write((uint)type.Properties.Count, TypeLayout.NativePointerSize);

            // 2. Pointers to Property Definitions
            foreach (MosaProperty property in type.Properties)
            {
                // Emit field name
                var fieldNameSymbol = EmitStringWithLength(property.FullName + Metadata.NameString, property.Name);

                // Emit property definition
                var propertyDefSymbol = Linker.CreateSymbol(property.FullName + Metadata.PropertyDefinition, SectionKind.ROData, TypeLayout.NativePointerAlignment, 0);
                var writer2           = new EndianAwareBinaryWriter(propertyDefSymbol.Stream, Architecture.Endianness);

                // 1. Name
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, (int)writer2.Position, 0, fieldNameSymbol, 0);
                writer2.WriteZeroBytes(TypeLayout.NativePointerSize);

                // 2. Pointer to Custom Attributes
                if (property.CustomAttributes.Count > 0)
                {
                    var customAttributesTableSymbol = CreateCustomAttributesTable(property);
                    Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, (int)writer1.Position, 0, customAttributesTableSymbol, 0);
                }
                writer1.WriteZeroBytes(TypeLayout.NativePointerSize);

                // 3. Attributes
                writer1.Write((uint)property.PropertyAttributes, TypeLayout.NativePointerSize);

                // 4. Pointer to Property Type
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, (int)writer2.Position, 0, property.PropertyType.FullName + Metadata.TypeDefinition, SectionKind.ROData, 0);
                writer2.WriteZeroBytes(TypeLayout.NativePointerSize);

                // If the type is a property then skip linking the methods
                if (!type.IsInterface)
                {
                    // 5. Pointer to Getter Method Definition
                    if (property.GetterMethod != null)
                    {
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, (int)writer2.Position, 0, property.GetterMethod.FullName + Metadata.MethodDefinition, SectionKind.ROData, 0);
                    }
                    writer2.WriteZeroBytes(TypeLayout.NativePointerSize);

                    // 6. Pointer to Setter Method Definition
                    if (property.SetterMethod != null)
                    {
                        Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertyDefSymbol, (int)writer2.Position, 0, property.SetterMethod.FullName + Metadata.MethodDefinition, SectionKind.ROData, 0);
                    }
                    writer2.WriteZeroBytes(TypeLayout.NativePointerSize);
                }
                else
                {
                    // Fill 5 and 6 with zeros.
                    writer1.WriteZeroBytes(TypeLayout.NativePointerSize * 2);
                }

                // Add pointer to properties table
                Linker.Link(LinkType.AbsoluteAddress, NativePatchType, propertiesTableSymbol, (int)writer1.Position, 0, propertyDefSymbol, 0);
                writer1.WriteZeroBytes(TypeLayout.NativePointerSize);
            }

            // Return fieldListTableSymbol for linker usage
            return(propertiesTableSymbol);
        }