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

            _methods.Sort(new CompilerComparer());
            GCRefMapBuilder builder = new GCRefMapBuilder(factory.Target, relocsOnly);
            builder.Builder.RequireInitialAlignment(4);
            builder.Builder.AddSymbol(this);

            // First, emit the initial ref map offset and reserve the offset map entries
            int offsetCount = _methods.Count / GCREFMAP_LOOKUP_STRIDE;
            builder.Builder.EmitInt((offsetCount + 1) * sizeof(int));

            ObjectDataBuilder.Reservation[] offsets = new ObjectDataBuilder.Reservation[offsetCount];
            for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++)
            {
                offsets[offsetIndex] = builder.Builder.ReserveInt();
            }

            // Next, generate the actual method GC ref maps and update the offset map
            int nextOffsetIndex = 0;
            int nextMethodIndex = GCREFMAP_LOOKUP_STRIDE - 1;
            for (int methodIndex = 0; methodIndex < _methods.Count; methodIndex++)
            {
                IMethodNode methodNode = _methods[methodIndex];
                if (methodNode == null)
                {
                    // Flush an empty GC ref map block to prevent
                    // the indexed records from falling out of sync with methods
                    builder.Flush();
                }
                else
                {
                    bool isUnboxingStub = false;
                    if (methodNode is DelayLoadHelperImport methodImport)
                    {
                        isUnboxingStub = ((MethodFixupSignature)methodImport.ImportSignature.Target).IsUnboxingStub;
                    }
                    builder.GetCallRefMap(methodNode.Method, isUnboxingStub);
                }
                if (methodIndex >= nextMethodIndex)
                {
                    builder.Builder.EmitInt(offsets[nextOffsetIndex], builder.Builder.CountBytes);
                    nextOffsetIndex++;
                    nextMethodIndex += GCREFMAP_LOOKUP_STRIDE;
                }
            }
            Debug.Assert(nextOffsetIndex == offsets.Length);

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

            GCRefMapBuilder builder = new GCRefMapBuilder(factory, relocsOnly);

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

            // First, emit the initial ref map offset and reserve the offset map entries
            int offsetCount = _methods.Count / GCREFMAP_LOOKUP_STRIDE;

            builder.Builder.EmitInt((offsetCount + 1) * sizeof(int));

            ObjectDataBuilder.Reservation[] offsets = new ObjectDataBuilder.Reservation[offsetCount];
            for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++)
            {
                offsets[offsetIndex] = builder.Builder.ReserveInt();
            }

            // Next, generate the actual method GC ref maps and update the offset map
            int nextOffsetIndex = 0;
            int nextMethodIndex = GCREFMAP_LOOKUP_STRIDE - 1;

            for (int methodIndex = 0; methodIndex < _methods.Count; methodIndex++)
            {
                if (methodIndex >= nextMethodIndex)
                {
                    builder.Builder.EmitInt(offsets[nextOffsetIndex], builder.Builder.CountBytes);
                    nextOffsetIndex++;
                    nextMethodIndex += GCREFMAP_LOOKUP_STRIDE;
                }
                MethodWithGCInfo methodNode = _methods[methodIndex];
                if (methodNode == null || methodNode.IsEmpty)
                {
                    // Flush an empty GC ref map block to prevent
                    // the indexed records from falling out of sync with methods
                    builder.Flush();
                }
                else
                {
                    builder.GetCallRefMap(methodNode.Method);
                }
            }
            Debug.Assert(nextOffsetIndex == offsets.Length);

            return(builder.Builder.ToObjectData());
        }
Esempio n. 3
0
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);

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

            EmitHeaderPrefix(ref builder);

            // Don't bother sorting if we're not emitting the contents
            if (!relocsOnly)
            {
                _items.MergeSort((x, y) => Comparer <int> .Default.Compare((int)x.Id, (int)y.Id));
            }

            // ReadyToRunHeader.Flags
            builder.EmitInt((int)_flags);

            // ReadyToRunHeader.NumberOfSections
            ObjectDataBuilder.Reservation sectionCountReservation = builder.ReserveInt();

            int count = 0;

            foreach (var item in _items)
            {
                // Skip empty entries
                if (!relocsOnly && item.Node is ObjectNode on && on.ShouldSkipEmittingObjectNode(factory))
                {
                    continue;
                }

                // Unmarked nodes are not part of the graph
                if (!item.Node.Marked && !(item.Node is ObjectNode))
                {
                    Debug.Assert(item.Node is DelayLoadMethodCallThunkNodeRange);
                    continue;
                }

                builder.EmitInt((int)item.Id);

                builder.EmitReloc(item.StartSymbol, RelocType.IMAGE_REL_BASED_ADDR32NB);

                // The header entry for the runtime functions table should not include the 4 byte 0xffffffff sentinel
                // value in the covered range.
                int delta = item.Id == ReadyToRunSectionType.RuntimeFunctions ? RuntimeFunctionsTableNode.SentinelSizeAdjustment : 0;
                builder.EmitReloc(item.StartSymbol, RelocType.IMAGE_REL_SYMBOL_SIZE, delta);

                count++;
            }

            builder.EmitInt(sectionCountReservation, count);

            return(builder.ToObjectData());
        }
Esempio n. 4
0
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);

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

            // Don't bother sorting if we're not emitting the contents
            if (!relocsOnly)
            {
                _items.Sort((x, y) => Comparer <int> .Default.Compare((int)x.Id, (int)y.Id));
            }

            // ReadyToRunHeader.Magic
            builder.EmitInt((int)(ReadyToRunHeaderConstants.Signature));

            // ReadyToRunHeader.MajorVersion
            builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMajorVersion));
            builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMinorVersion));

            // ReadyToRunHeader.Flags
            builder.EmitInt(0);

            // ReadyToRunHeader.NumberOfSections
            ObjectDataBuilder.Reservation sectionCountReservation = builder.ReserveInt();

            int count = 0;

            foreach (var item in _items)
            {
                // Skip empty entries
                if (!relocsOnly && item.Node.ShouldSkipEmittingObjectNode(factory))
                {
                    continue;
                }

                builder.EmitInt((int)item.Id);

                builder.EmitReloc(item.StartSymbol, RelocType.IMAGE_REL_BASED_ADDR32NB);

                if (!relocsOnly)
                {
                    builder.EmitInt(item.Node.GetData(factory).Data.Length);
                }

                count++;
            }

            builder.EmitInt(sectionCountReservation, count);

            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);

            EmitHeaderPrefix(ref builder);

            // Don't bother sorting if we're not emitting the contents
            if (!relocsOnly)
            {
                _items.MergeSort((x, y) => Comparer <int> .Default.Compare((int)x.Id, (int)y.Id));
            }

            // ReadyToRunHeader.Flags
            builder.EmitInt((int)_flags);

            // ReadyToRunHeader.NumberOfSections
            ObjectDataBuilder.Reservation sectionCountReservation = builder.ReserveInt();

            int count = 0;

            foreach (var item in _items)
            {
                // Skip empty entries
                if (!relocsOnly && item.Node.ShouldSkipEmittingObjectNode(factory))
                {
                    continue;
                }

                builder.EmitInt((int)item.Id);

                builder.EmitReloc(item.StartSymbol, RelocType.IMAGE_REL_BASED_ADDR32NB);
                builder.EmitReloc(item.StartSymbol, RelocType.IMAGE_REL_SYMBOL_SIZE);

                count++;
            }

            builder.EmitInt(sectionCountReservation, count);

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

            _methods.Sort(new CompilerComparer());
            GCRefMapBuilder builder = new GCRefMapBuilder(factory.Target, relocsOnly);

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

            // First, emit the initial ref map offset and reserve the offset map entries
            int offsetCount = _methods.Count / GCREFMAP_LOOKUP_STRIDE;

            builder.Builder.EmitInt((offsetCount + 1) * sizeof(int));

            ObjectDataBuilder.Reservation[] offsets = new ObjectDataBuilder.Reservation[offsetCount];
            for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++)
            {
                offsets[offsetIndex] = builder.Builder.ReserveInt();
            }

            // Next, generate the actual method GC ref maps and update the offset map
            int nextOffsetIndex = 0;
            int nextMethodIndex = GCREFMAP_LOOKUP_STRIDE - 1;

            for (int methodIndex = 0; methodIndex < _methods.Count; methodIndex++)
            {
                IMethodNode methodNode = _methods[methodIndex];
                if (methodNode == null || (methodNode is LocalMethodImport localMethod && localMethod.MethodCodeNode.IsEmpty))
                {
                    // Flush an empty GC ref map block to prevent
                    // the indexed records from falling out of sync with methods
                    builder.Flush();
                }