Esempio n. 1
0
        public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly)
        {
            if (relocsOnly)
            {
                return;
            }

            TargetArchitecture targetArch = factory.Target.Architecture;

            for (int frameInfoIndex = 0; frameInfoIndex < _methodNode.FrameInfos.Length; frameInfoIndex++)
            {
                byte[] unwindInfo = _methodNode.FrameInfos[frameInfoIndex].BlobData;

                if (targetArch == TargetArchitecture.X64)
                {
                    // On Amd64, patch the first byte of the unwind info by setting the flags to EHANDLER | UHANDLER
                    // as that's what CoreCLR does (zapcode.cpp, ZapUnwindData::Save).
                    const byte UNW_FLAG_EHANDLER = 1;
                    const byte UNW_FLAG_UHANDLER = 2;
                    const byte FlagsShift        = 3;

                    unwindInfo[0] |= (byte)((UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER) << FlagsShift);
                }
                else if ((targetArch == TargetArchitecture.ARM) || (targetArch == TargetArchitecture.ARM64))
                {
                    // Set the 'X' bit to indicate that there is a personality routine associated with this method
                    unwindInfo[2] |= 1 << 4;
                }

                dataBuilder.EmitBytes(unwindInfo);
                // 4-align after emitting the unwind info
                dataBuilder.EmitZeros(-unwindInfo.Length & 3);

                if (targetArch != TargetArchitecture.X86)
                {
                    bool        isFilterFunclet    = (_methodNode.FrameInfos[frameInfoIndex].Flags & FrameInfoFlags.Filter) != 0;
                    ISymbolNode personalityRoutine = (isFilterFunclet ? factory.FilterFuncletPersonalityRoutine : factory.PersonalityRoutine);
                    int         codeDelta          = 0;
                    if (targetArch == TargetArchitecture.ARM)
                    {
                        // THUMB_CODE
                        codeDelta = 1;
                    }
                    dataBuilder.EmitReloc(personalityRoutine, RelocType.IMAGE_REL_BASED_ADDR32NB, codeDelta);
                }

                if (frameInfoIndex == 0 && _methodNode.GCInfo != null)
                {
                    dataBuilder.EmitBytes(_methodNode.GCInfo);

                    // Maintain 4-alignment for the next unwind / GC info block
                    int align4Pad = -_methodNode.GCInfo.Length & 3;
                    dataBuilder.EmitZeros(align4Pad);
                }
            }
        }
Esempio n. 2
0
        public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly)
        {
            if (relocsOnly)
            {
                return;
            }

            bool isFound = factory.RuntimeFunctionsGCInfo.Deduplicator.TryGetValue(this, out var found);

            if (isFound && (found != this))
            {
                return;
            }

            factory.RuntimeFunctionsGCInfo.Deduplicator.Add(this);

            foreach (var item in EncodeDataCore(factory))
            {
                if (item.Bytes != null)
                {
                    dataBuilder.EmitBytes(item.Bytes);
                    // Maintain 4-alignment for the next unwind / GC info block
                    int align4Pad = -item.Bytes.Length & 3;
                    dataBuilder.EmitZeros(align4Pad);
                }
                else
                {
                    dataBuilder.EmitReloc(item.Symbol, RelocType.IMAGE_REL_BASED_ADDR32NB, item.SymbolDelta);
                }
            }
        }
Esempio n. 3
0
        private void WriteMethodTableRvas(NodeFactory factory, ref ObjectDataBuilder builder, ref BlobReader reader)
        {
            MetadataReader metadataReader = _sourceModule.MetadataReader;
            var            tableIndex     = TableIndex.MethodDef;
            int            rowCount       = metadataReader.GetTableRowCount(tableIndex);
            int            rowSize        = metadataReader.GetTableRowSize(tableIndex);

            for (int i = 1; i <= rowCount; i++)
            {
                Debug.Assert(builder.CountBytes == reader.Offset);

                int inputRva = reader.ReadInt32();

                if (inputRva == 0)
                {
                    // Don't fix up 0 Rvas (abstract methods in the methodDef table)
                    builder.EmitInt(0);
                }
                else
                {
                    var        methodDefHandle = MetadataTokens.EntityHandle(TableIndex.MethodDef, i);
                    EcmaMethod method          = _sourceModule.GetMethod(methodDefHandle) as EcmaMethod;
                    builder.EmitReloc(((ReadyToRunCodegenNodeFactory)factory).CopiedMethodIL(method), RelocType.IMAGE_REL_BASED_ADDR32NB);
                }

                // Skip the rest of the row
                int remainingBytes = rowSize - sizeof(int);
                builder.EmitBytes(reader.ReadBytes(remainingBytes));
            }
        }
Esempio n. 4
0
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);

            builder.AddSymbol(this);
            builder.EmitBytes(Encoding.UTF8.GetBytes(_ownerExecutableName));
            builder.EmitByte(0); // zero string terminator
            return(builder.ToObjectData());
        }
Esempio n. 5
0
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);

            builder.RequireInitialPointerAlignment();
            builder.AddSymbol(this);
            builder.EmitBytes(Encoding.ASCII.GetBytes(_compilerIdentifier));
            return(builder.ToObjectData());
        }
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);

            builder.RequireInitialPointerAlignment();
            builder.AddSymbol(this);
            builder.EmitBytes(Encoding.UTF8.GetBytes(_ownerExecutableName));
            return(builder.ToObjectData());
        }
Esempio n. 7
0
        public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly)
        {
            if (relocsOnly)
            {
                return;
            }
            for (int frameInfoIndex = 0; frameInfoIndex < _methodNode.FrameInfos.Length; frameInfoIndex++)
            {
                byte[] unwindInfo = _methodNode.FrameInfos[frameInfoIndex].BlobData;

                if (factory.Target.Architecture == Internal.TypeSystem.TargetArchitecture.X64)
                {
                    // On Amd64, patch the first byte of the unwind info by setting the flags to EHANDLER | UHANDLER
                    // as that's what CoreCLR does (zapcode.cpp, ZapUnwindData::Save).
                    const byte UNW_FLAG_EHANDLER = 1;
                    const byte UNW_FLAG_UHANDLER = 2;
                    const byte FlagsShift        = 3;

                    unwindInfo[0] |= (byte)((UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER) << FlagsShift);
                }

                dataBuilder.EmitBytes(unwindInfo);
                // 4-align after emitting the unwind info
                dataBuilder.EmitZeros(-unwindInfo.Length & 3);

                if (factory.Target.Architecture != Internal.TypeSystem.TargetArchitecture.X86)
                {
                    bool isFilterFunclet = (_methodNode.FrameInfos[frameInfoIndex].Flags & FrameInfoFlags.Filter) != 0;
                    ReadyToRunCodegenNodeFactory r2rFactory = (ReadyToRunCodegenNodeFactory)factory;
                    ISymbolNode personalityRoutine          = (isFilterFunclet ? r2rFactory.FilterFuncletPersonalityRoutine : r2rFactory.PersonalityRoutine);
                    dataBuilder.EmitReloc(personalityRoutine, RelocType.IMAGE_REL_BASED_ADDR32NB);
                }

                if (frameInfoIndex == 0 && _methodNode.GCInfo != null)
                {
                    dataBuilder.EmitBytes(_methodNode.GCInfo);

                    // Maintain 4-alignment for the next unwind / GC info block
                    int align4Pad = -_methodNode.GCInfo.Length & 3;
                    dataBuilder.EmitZeros(align4Pad);
                }
            }
        }
        public void WriteData(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly = false)
        {
            int offset = Offset;

            if (FixupInfos != null)
            {
                int startOffset = builder.CountBytes;

                for (int i = 0; i < FixupInfos.Count; ++i)
                {
                    var fixupInfo = FixupInfos[i];

                    // do we have overlapping fixups?
                    if (fixupInfo.Offset < offset)
                    {
                        throw new BadImageFormatException();
                    }

                    if (!relocsOnly)
                    {
                        // emit bytes before fixup
                        builder.EmitBytes(Data, offset, fixupInfo.Offset - offset);
                    }

                    // write the fixup
                    FixupInfos[i].WriteData(ref builder, factory);

                    // move pointer past the fixup
                    offset = Offset + builder.CountBytes - startOffset;
                }
            }

            if (offset > Data.Length)
            {
                throw new BadImageFormatException();
            }

            if (!relocsOnly)
            {
                // Emit remaining bytes
                builder.EmitBytes(Data, offset, Data.Length - offset);
            }
        }
Esempio n. 9
0
        public unsafe override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);

            builder.RequireInitialPointerAlignment();
            builder.AddSymbol(this);

            BlobReader metadataBlob   = new BlobReader(_sourceModule.PEReader.GetMetadata().Pointer, _sourceModule.PEReader.GetMetadata().Length);
            var        metadataReader = _sourceModule.MetadataReader;

            //
            // methodDef table
            //

            int methodDefTableOffset = metadataReader.GetTableMetadataOffset(TableIndex.MethodDef);

            builder.EmitBytes(metadataBlob.ReadBytes(methodDefTableOffset));

            WriteMethodTableRvas(factory, ref builder, ref metadataBlob);

            //
            // fieldRva table
            //

            int fieldRvaTableOffset = metadataReader.GetTableMetadataOffset(TableIndex.FieldRva);

            builder.EmitBytes(metadataBlob.ReadBytes(fieldRvaTableOffset - metadataBlob.Offset));

            WriteFieldRvas(factory, ref builder, ref metadataBlob);

            // Copy the rest of the metadata blob
            builder.EmitBytes(metadataBlob.ReadBytes(metadataReader.MetadataLength - metadataBlob.Offset));

            Debug.Assert(builder.CountBytes == metadataBlob.Length);
            Debug.Assert(builder.CountBytes == metadataBlob.Offset);
            Debug.Assert(builder.CountBytes == Size);

            return(builder.ToObjectData());
        }
Esempio n. 10
0
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            if (relocsOnly)
            {
                return(new ObjectData(
                           data: Array.Empty <byte>(),
                           relocs: Array.Empty <Relocation>(),
                           alignment: 1,
                           definedSymbols: new ISymbolDefinitionNode[] { this }));
            }

            ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);

            builder.RequireInitialPointerAlignment();
            builder.AddSymbol(this);
            builder.EmitBytes(GetRvaData(factory.Target.PointerSize));
            return(builder.ToObjectData());
        }
Esempio n. 11
0
        public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly)
        {
            ProfileDataNode nextElementInList = ((ProfileDataSectionNode)ContainingNode).NextElementToEncode;

            if (nextElementInList != null)
            {
                dataBuilder.EmitPointerReloc(nextElementInList, -OffsetFromStartOfObjectToSymbol);
            }
            else
            {
                dataBuilder.EmitZeroPointer();
            }

            if (relocsOnly)
            {
                return;
            }

            EcmaMethod ecmaMethod  = (EcmaMethod)_methodNode.Method.GetTypicalMethodDefinition();
            int        startOffset = dataBuilder.CountBytes;
            var        reservation = dataBuilder.ReserveInt();

            dataBuilder.EmitInt(0);                                                     // CORBBTPROF_METHOD_HEADER::cDetail
            dataBuilder.EmitInt(ecmaMethod.MetadataReader.GetToken(ecmaMethod.Handle)); // CORBBT_METHOD_INFO::token
            dataBuilder.EmitInt(_ilSize);                                               // CORBBT_METHOD_INFO::ILSize
            dataBuilder.EmitInt(_blockCount);                                           // CORBBT_METHOD_INFO::cBlock
            int sizeOfCORBBTPROF_METHOD_HEADER = dataBuilder.CountBytes - startOffset;

            Debug.Assert(sizeOfCORBBTPROF_METHOD_HEADER == (OffsetFromStartOfObjectToSymbol - _targetDetails.PointerSize));
            dataBuilder.EmitInt(reservation, sizeOfCORBBTPROF_METHOD_HEADER + _profileData.Length);

            dataBuilder.EmitBytes(_profileData);

            while ((dataBuilder.CountBytes & (dataBuilder.TargetPointerSize - 1)) != 0)
            {
                dataBuilder.EmitByte(0);
            }
        }
Esempio n. 12
0
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            if (relocsOnly)
            {
                return(new ObjectData(
                           data: Array.Empty <byte>(),
                           relocs: Array.Empty <Relocation>(),
                           alignment: 1,
                           definedSymbols: new ISymbolDefinitionNode[] { this }));
            }

            ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);

            builder.RequireInitialAlignment(4);
            builder.AddSymbol(this);

            DirectoryEntry resourcesDirectory = _module.PEReader.PEHeaders.CorHeader.ResourcesDirectory;
            PEMemoryBlock  block = _module.PEReader.GetSectionData(resourcesDirectory.RelativeVirtualAddress);

            builder.EmitBytes(block.GetReader().ReadBytes(resourcesDirectory.Size));

            return(builder.ToObjectData());
        }
Esempio n. 13
0
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            // This node does not trigger generation of other nodes.
            if (relocsOnly)
            {
                return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this }));
            }

            List <CustomAttributeEntry> customAttributeEntries = GetCustomAttributeEntries();
            int countOfEntries = customAttributeEntries.Count;

            if (countOfEntries == 0)
            {
                return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this }));
            }

            // Buckets have 8 entries
            uint minTableBucketCount = (uint)(countOfEntries / 8) + 1;
            uint bucketCount         = 1;

            // Bucket count must be power of two
            while (bucketCount < minTableBucketCount)
            {
                bucketCount *= 2;
            }

            // Resize the array.
            bool tryAgainWithBiggerTable = false;
            int  countOfRetries          = 0;

            ushort[] pTable;
            do
            {
                tryAgainWithBiggerTable = false;
                uint actualSizeOfTable = bucketCount * 8; // Buckets have 8 entries in them
                pTable = new ushort[actualSizeOfTable];
                uint[] state = new uint[] { 729055690, 833774698, 218408041, 493449127 };
                // Attempt to fill table
                foreach (var customAttributeEntry in customAttributeEntries)
                {
                    string name = customAttributeEntry.TypeNamespace + "." + customAttributeEntry.TypeName;
                    // This hashing algorithm MUST match exactly the logic in NativeCuckooFilter
                    int    hashOfAttribute = ReadyToRunHashCode.NameHashCode(name);
                    uint   hash            = unchecked ((uint)ReadyToRunHashCode.CombineTwoValuesIntoHash((uint)hashOfAttribute, (uint)customAttributeEntry.Parent));
                    ushort fingerprint     = (ushort)(hash >> 16);
                    if (fingerprint == 0)
                    {
                        fingerprint = 1;
                    }
                    uint bucketAIndex    = hash % bucketCount;
                    uint fingerprintHash = (uint)fingerprint;
                    uint bucketBIndex    = (bucketAIndex ^ (fingerprintHash % bucketCount));
                    Debug.Assert(bucketAIndex == (bucketBIndex ^ (fingerprintHash % bucketCount)));
                    if ((XorShift128(state) & 1) != 0) // Randomly choose which bucket to attempt to fill first
                    {
                        uint temp = bucketAIndex;
                        bucketAIndex = bucketBIndex;
                        bucketBIndex = temp;
                    }
                    Func <uint, ushort, bool> hasEntryInBucket = (uint bucketIndex, ushort fprint) =>
                    {
                        for (int i = 0; i < 8; i++)
                        {
                            if (pTable[(bucketIndex * 8) + i] == fprint)
                            {
                                return(true);
                            }
                        }
                        return(false);
                    };
                    Func <uint, bool> isEmptyEntryInBucket = (uint bucketIndex) =>
                    {
                        for (int i = 0; i < 8; i++)
                        {
                            if (pTable[(bucketIndex * 8) + i] == 0)
                            {
                                return(true);
                            }
                        }
                        return(false);
                    };
                    Action <uint, ushort> fillEmptyEntryInBucket = (uint bucketIndex, ushort fprint) =>
                    {
                        for (int i = 0; i < 8; i++)
                        {
                            if (pTable[(bucketIndex * 8) + i] == 0)
                            {
                                pTable[(bucketIndex * 8) + i] = fprint;
                                return;
                            }
                        }
                        Debug.Assert(false, "Not possible to reach here");
                    };
                    // Scan for pre-existing fingerprint entry in buckets
                    if (hasEntryInBucket(bucketAIndex, fingerprint) || hasEntryInBucket(bucketBIndex, fingerprint))
                    {
                        continue;
                    }

                    // Determine if there is space in a bucket to add a new entry
                    if (isEmptyEntryInBucket(bucketAIndex))
                    {
                        fillEmptyEntryInBucket(bucketAIndex, fingerprint);
                        continue;
                    }

                    if (isEmptyEntryInBucket(bucketBIndex))
                    {
                        fillEmptyEntryInBucket(bucketBIndex, fingerprint);
                        continue;
                    }

                    bool success     = false;
                    int  MaxNumKicks = 256;
                    // Note, that bucketAIndex itself was chosen randomly above.
                    for (int n = 0; !success && n < MaxNumKicks; n++)
                    {
                        // Randomly swap an entry in bucket bucketAIndex with fingerprint
                        uint   entryIndexInBucket = XorShift128(state) & 0x7;
                        ushort temp = fingerprint;
                        fingerprint = pTable[(bucketAIndex * 8) + entryIndexInBucket];
                        pTable[(bucketAIndex * 8) + entryIndexInBucket] = temp;

                        // Find other bucket
                        fingerprintHash = (uint)fingerprint;
                        bucketAIndex    = bucketAIndex ^ (fingerprintHash % bucketCount);
                        if (isEmptyEntryInBucket(bucketAIndex))
                        {
                            fillEmptyEntryInBucket(bucketAIndex, fingerprint);
                            success = true;
                        }
                    }

                    if (success)
                    {
                        continue;
                    }

                    tryAgainWithBiggerTable = true;
                }

                if (tryAgainWithBiggerTable)
                {
                    // bucket entry kicking path requires bucket counts to be power of two in size due to use of xor to retrieve second hash
                    bucketCount *= 2;
                }
            }while(tryAgainWithBiggerTable && ((countOfRetries++) < 2));

            byte[] result;
            if (tryAgainWithBiggerTable)
            {
                result = Array.Empty <byte>();
            }
            else
            {
                result = new byte[pTable.Length * 2];
                for (int i = 0; i < pTable.Length; i++)
                {
                    result[i * 2]     = (byte)(pTable[i] % 256);
                    result[i * 2 + 1] = (byte)(pTable[i] >> 8);
                }
            }

            ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);

            builder.RequireInitialAlignment(16);
            builder.AddSymbol(this);
            builder.EmitBytes(result);

            return(builder.ToObjectData());;
        }
Esempio n. 14
0
        public void WriteResources(ISymbolNode nodeAssociatedWithDataBuilder, ref ObjectDataBuilder dataBuilder)
        {
            Debug.Assert(dataBuilder.CountBytes == 0);

            SortedDictionary <string, List <ObjectDataBuilder.Reservation> > nameTable = new SortedDictionary <string, List <ObjectDataBuilder.Reservation> >();
            Dictionary <ResLanguage, int> dataEntryTable = new Dictionary <ResLanguage, int>();
            List <Tuple <ResType, ObjectDataBuilder.Reservation> >     resTypes     = new List <Tuple <ResType, ObjectDataBuilder.Reservation> >();
            List <Tuple <ResName, ObjectDataBuilder.Reservation> >     resNames     = new List <Tuple <ResName, ObjectDataBuilder.Reservation> >();
            List <Tuple <ResLanguage, ObjectDataBuilder.Reservation> > resLanguages = new List <Tuple <ResLanguage, ObjectDataBuilder.Reservation> >();

            IMAGE_RESOURCE_DIRECTORY.Write(ref dataBuilder, checked ((ushort)_resTypeHeadName.Count), checked ((ushort)_resTypeHeadID.Count));
            foreach (KeyValuePair <string, ResType> res in _resTypeHeadName)
            {
                resTypes.Add(new Tuple <ResType, ObjectDataBuilder.Reservation>(res.Value, IMAGE_RESOURCE_DIRECTORY_ENTRY.Write(ref dataBuilder, res.Key, nameTable)));
            }
            foreach (KeyValuePair <ushort, ResType> res in _resTypeHeadID)
            {
                resTypes.Add(new Tuple <ResType, ObjectDataBuilder.Reservation>(res.Value, IMAGE_RESOURCE_DIRECTORY_ENTRY.Write(ref dataBuilder, res.Key)));
            }

            foreach (Tuple <ResType, ObjectDataBuilder.Reservation> type in resTypes)
            {
                dataBuilder.EmitUInt(type.Item2, (uint)dataBuilder.CountBytes | 0x80000000);
                IMAGE_RESOURCE_DIRECTORY.Write(ref dataBuilder, checked ((ushort)type.Item1.NameHeadName.Count), checked ((ushort)type.Item1.NameHeadID.Count));

                foreach (KeyValuePair <string, ResName> res in type.Item1.NameHeadName)
                {
                    resNames.Add(new Tuple <ResName, ObjectDataBuilder.Reservation>(res.Value, IMAGE_RESOURCE_DIRECTORY_ENTRY.Write(ref dataBuilder, res.Key, nameTable)));
                }
                foreach (KeyValuePair <ushort, ResName> res in type.Item1.NameHeadID)
                {
                    resNames.Add(new Tuple <ResName, ObjectDataBuilder.Reservation>(res.Value, IMAGE_RESOURCE_DIRECTORY_ENTRY.Write(ref dataBuilder, res.Key)));
                }
            }

            foreach (Tuple <ResName, ObjectDataBuilder.Reservation> type in resNames)
            {
                dataBuilder.EmitUInt(type.Item2, (uint)dataBuilder.CountBytes | 0x80000000);
                IMAGE_RESOURCE_DIRECTORY.Write(ref dataBuilder, 0, checked ((ushort)type.Item1.Languages.Count));
                foreach (KeyValuePair <ushort, ResLanguage> res in type.Item1.Languages)
                {
                    resLanguages.Add(new Tuple <ResLanguage, ObjectDataBuilder.Reservation>(res.Value, IMAGE_RESOURCE_DIRECTORY_ENTRY.Write(ref dataBuilder, res.Key)));
                }
            }

            // Emit name table
            dataBuilder.PadAlignment(2); // name table is 2 byte aligned
            foreach (KeyValuePair <string, List <ObjectDataBuilder.Reservation> > name in nameTable)
            {
                foreach (ObjectDataBuilder.Reservation reservation in name.Value)
                {
                    dataBuilder.EmitUInt(reservation, (uint)dataBuilder.CountBytes | 0x80000000);
                }

                dataBuilder.EmitUShort(checked ((ushort)name.Key.Length));
                foreach (char c in name.Key)
                {
                    dataBuilder.EmitUShort((ushort)c);
                }
            }

            // Emit byte arrays of resource data, capture the offsets
            foreach (Tuple <ResLanguage, ObjectDataBuilder.Reservation> language in resLanguages)
            {
                dataBuilder.PadAlignment(4); // Data in resource files is 4 byte aligned
                dataEntryTable.Add(language.Item1, dataBuilder.CountBytes);
                dataBuilder.EmitBytes(language.Item1.DataEntry);
            }

            dataBuilder.PadAlignment(4); // resource data entries are 4 byte aligned
            foreach (Tuple <ResLanguage, ObjectDataBuilder.Reservation> language in resLanguages)
            {
                dataBuilder.EmitInt(language.Item2, dataBuilder.CountBytes);
                IMAGE_RESOURCE_DATA_ENTRY.Write(ref dataBuilder, nodeAssociatedWithDataBuilder, dataEntryTable[language.Item1], language.Item1.DataEntry.Length);
            }
            dataBuilder.PadAlignment(4); // resource data entries are 4 byte aligned
        }
Esempio n. 15
0
        private void ComputeDependencyNodeDependencies(List <DependencyNodeCore <NodeFactory> > obj)
        {
            foreach (MethodCodeNode methodCodeNodeNeedingCode in obj)
            {
                MethodDesc method     = methodCodeNodeNeedingCode.Method;
                string     methodName = method.ToString();
                Log.WriteLine("Compiling " + methodName);

                var methodIL = _ilProvider.GetMethodIL(method);
                if (methodIL == null)
                {
                    return;
                }

                MethodCode methodCode;
                try
                {
                    if (_skipJitList.Contains(new TypeAndMethod(method.OwningType.Name, method.Name)))
                    {
                        throw new NotImplementedException("SkipJIT");
                    }

                    methodCode = _corInfo.CompileMethod(method);

                    if (methodCode.Relocs != null)
                    {
                        if (methodCode.Relocs.Any(r => r.Target is FieldDesc))
                        {
                            // We only support FieldDesc for InitializeArray intrinsic right now.
                            throw new NotImplementedException("RuntimeFieldHandle is not implemented");
                        }
                    }
                }
                catch (Exception e)
                {
                    Log.WriteLine("*** " + e.Message + " (" + method + ")");

                    // Call the __not_yet_implemented method
                    DependencyAnalysis.X64.X64Emitter emit = new DependencyAnalysis.X64.X64Emitter(_nodeFactory);
                    emit.Builder.RequireAlignment(_nodeFactory.Target.MinimumFunctionAlignment);
                    emit.Builder.DefinedSymbols.Add(methodCodeNodeNeedingCode);

                    emit.EmitLEAQ(emit.TargetRegister.Arg0, _nodeFactory.StringIndirection(method.ToString()));
                    DependencyAnalysis.X64.AddrMode loadFromArg0 =
                        new DependencyAnalysis.X64.AddrMode(emit.TargetRegister.Arg0, null, 0, 0, DependencyAnalysis.X64.AddrModeSize.Int64);
                    emit.EmitMOV(emit.TargetRegister.Arg0, ref loadFromArg0);
                    emit.EmitMOV(emit.TargetRegister.Arg0, ref loadFromArg0);

                    emit.EmitLEAQ(emit.TargetRegister.Arg1, _nodeFactory.StringIndirection(e.Message));
                    DependencyAnalysis.X64.AddrMode loadFromArg1 =
                        new DependencyAnalysis.X64.AddrMode(emit.TargetRegister.Arg1, null, 0, 0, DependencyAnalysis.X64.AddrModeSize.Int64);
                    emit.EmitMOV(emit.TargetRegister.Arg1, ref loadFromArg1);
                    emit.EmitMOV(emit.TargetRegister.Arg1, ref loadFromArg1);

                    emit.EmitJMP(_nodeFactory.ExternSymbol("__not_yet_implemented"));
                    methodCodeNodeNeedingCode.SetCode(emit.Builder.ToObjectData());
                    continue;
                }

                ObjectDataBuilder objData = new ObjectDataBuilder();
                objData.Alignment = _nodeFactory.Target.MinimumFunctionAlignment;
                objData.EmitBytes(methodCode.Code);
                objData.DefinedSymbols.Add(methodCodeNodeNeedingCode);

                BlobNode readOnlyDataBlob = null;
                if (methodCode.ROData != null)
                {
                    readOnlyDataBlob = _nodeFactory.ReadOnlyDataBlob(
                        "__readonlydata_" + _nameMangler.GetMangledMethodName(method),
                        methodCode.ROData, methodCode.RODataAlignment);
                }

                if (methodCode.Relocs != null)
                {
                    for (int i = 0; i < methodCode.Relocs.Length; i++)
                    {
                        // TODO: Arbitrary relocs
                        if (methodCode.Relocs[i].Block != BlockType.Code)
                        {
                            throw new NotImplementedException();
                        }

                        int         offset    = methodCode.Relocs[i].Offset;
                        int         delta     = methodCode.Relocs[i].Delta;
                        RelocType   relocType = (RelocType)methodCode.Relocs[i].RelocType;
                        ISymbolNode targetNode;

                        object target = methodCode.Relocs[i].Target;
                        if (target is MethodDesc)
                        {
                            targetNode = _nodeFactory.MethodEntrypoint((MethodDesc)target);
                        }
                        else if (target is ReadyToRunHelper)
                        {
                            targetNode = _nodeFactory.ReadyToRunHelper((ReadyToRunHelper)target);
                        }
                        else if (target is JitHelper)
                        {
                            targetNode = _nodeFactory.ExternSymbol(((JitHelper)target).MangledName);
                        }
                        else if (target is string)
                        {
                            targetNode = _nodeFactory.StringIndirection((string)target);
                        }
                        else if (target is TypeDesc)
                        {
                            targetNode = _nodeFactory.NecessaryTypeSymbol((TypeDesc)target);
                        }
                        else if (target is RvaFieldData)
                        {
                            var rvaFieldData = (RvaFieldData)target;
                            targetNode = _nodeFactory.ReadOnlyDataBlob(rvaFieldData.MangledName,
                                                                       rvaFieldData.Data, _typeSystemContext.Target.PointerSize);
                        }
                        else if (target is BlockRelativeTarget)
                        {
                            var blockRelativeTarget = (BlockRelativeTarget)target;
                            // TODO: Arbitrary block relative relocs
                            if (blockRelativeTarget.Block != BlockType.ROData)
                            {
                                throw new NotImplementedException();
                            }
                            targetNode = readOnlyDataBlob;
                        }
                        else
                        {
                            // TODO:
                            throw new NotImplementedException();
                        }

                        objData.AddRelocAtOffset(targetNode, relocType, offset, delta);
                    }
                }
                // TODO: ColdCode
                if (methodCode.ColdCode != null)
                {
                    throw new NotImplementedException();
                }

                methodCodeNodeNeedingCode.SetCode(objData.ToObjectData());

                methodCodeNodeNeedingCode.InitializeFrameInfos(methodCode.FrameInfos);
                methodCodeNodeNeedingCode.InitializeDebugLocInfos(methodCode.DebugLocInfos);
            }
        }