Example #1
0
        public static ObjectData GetDataForPreInitDataField(
            ISymbolDefinitionNode node,
            MetadataType _type, List <PreInitFieldInfo> sortedPreInitFields,
            int startOffset,
            NodeFactory factory, bool relocsOnly = false)
        {
            ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);

            builder.RequireInitialAlignment(_type.GCStaticFieldAlignment.AsInt);

            int staticOffset    = startOffset;
            int staticOffsetEnd = _type.GCStaticFieldSize.AsInt;
            int idx             = 0;

            while (staticOffset < staticOffsetEnd)
            {
                PreInitFieldInfo fieldInfo = idx < sortedPreInitFields.Count ? sortedPreInitFields[idx] : null;
                int writeTo = staticOffsetEnd;
                if (fieldInfo != null)
                {
                    writeTo = fieldInfo.Field.Offset.AsInt;
                }

                // Emit the zero before the next preinitField
                builder.EmitZeros(writeTo - staticOffset);
                staticOffset = writeTo;

                if (fieldInfo != null)
                {
                    int count = builder.CountBytes;

                    if (fieldInfo.Field.FieldType.IsValueType)
                    {
                        // Emit inlined data for value types
                        fieldInfo.WriteData(ref builder, factory);
                    }
                    else
                    {
                        // Emit a pointer reloc to the frozen data for reference types
                        builder.EmitPointerReloc(factory.SerializedFrozenArray(fieldInfo));
                    }

                    staticOffset += builder.CountBytes - count;
                    idx++;
                }
            }

            builder.AddSymbol(node);

            return(builder.ToObjectData());
        }
        public static string GetBaseSymbolName(ISymbolNode symbol, NameMangler nameMangler, bool objectWriterUse = false)
        {
            if (symbol is WebAssemblyMethodCodeNode)
            {
                return(symbol.GetMangledName(nameMangler));
            }

            if (symbol is ObjectNode)
            {
                ObjectNode            objNode       = (ObjectNode)symbol;
                ISymbolDefinitionNode symbolDefNode = (ISymbolDefinitionNode)symbol;
                if (symbolDefNode.Offset == 0)
                {
                    return(symbol.GetMangledName(nameMangler));
                }
                else
                {
                    return(symbol.GetMangledName(nameMangler) + "___REALBASE");
                }
            }
            else if (symbol is ObjectAndOffsetSymbolNode)
            {
                ObjectAndOffsetSymbolNode objAndOffset = (ObjectAndOffsetSymbolNode)symbol;
                if (objAndOffset.Target is IHasStartSymbol)
                {
                    ISymbolNode startSymbol = ((IHasStartSymbol)objAndOffset.Target).StartSymbol;
                    if (startSymbol == symbol)
                    {
                        Debug.Assert(startSymbol.Offset == 0);
                        return(symbol.GetMangledName(nameMangler));
                    }
                    return(GetBaseSymbolName(startSymbol, nameMangler, objectWriterUse));
                }
                return(GetBaseSymbolName((ISymbolNode)objAndOffset.Target, nameMangler, objectWriterUse));
            }
            else if (symbol is EmbeddedObjectNode)
            {
                EmbeddedObjectNode embeddedNode = (EmbeddedObjectNode)symbol;
                return(GetBaseSymbolName(embeddedNode.ContainingNode.StartSymbol, nameMangler, objectWriterUse));
            }
            else
            {
                return(null);
            }
        }
        private static int GetNumericOffsetFromBaseSymbolValue(ISymbolNode symbol)
        {
            if (symbol is WebAssemblyMethodCodeNode)
            {
                return(0);
            }

            if (symbol is ObjectNode)
            {
                ISymbolDefinitionNode symbolDefNode = (ISymbolDefinitionNode)symbol;
                return(symbolDefNode.Offset);
            }
            else if (symbol is ObjectAndOffsetSymbolNode)
            {
                ObjectAndOffsetSymbolNode objAndOffset  = (ObjectAndOffsetSymbolNode)symbol;
                ISymbolDefinitionNode     symbolDefNode = (ISymbolDefinitionNode)symbol;
                if (objAndOffset.Target is IHasStartSymbol)
                {
                    ISymbolNode startSymbol = ((IHasStartSymbol)objAndOffset.Target).StartSymbol;

                    if (startSymbol == symbol)
                    {
                        Debug.Assert(symbolDefNode.Offset == 0);
                        return(symbolDefNode.Offset);
                    }
                    return(symbolDefNode.Offset);
                }
                int baseOffset = GetNumericOffsetFromBaseSymbolValue((ISymbolNode)objAndOffset.Target);
                return(baseOffset + symbolDefNode.Offset);
            }
            else if (symbol is EmbeddedObjectNode)
            {
                EmbeddedObjectNode embeddedNode = (EmbeddedObjectNode)symbol;
                int baseOffset = GetNumericOffsetFromBaseSymbolValue(embeddedNode.ContainingNode.StartSymbol);
                return(baseOffset + ((ISymbolDefinitionNode)embeddedNode).Offset);
            }
            else
            {
                ThrowHelper.ThrowInvalidProgramException();
                return(0);
            }
        }
        public static ObjectData GetDataForPreInitDataField(
            ISymbolDefinitionNode node,
            MetadataType _type, List <PreInitFieldInfo> sortedPreInitFields,
            int startOffset,
            NodeFactory factory, bool relocsOnly = false)
        {
            ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);

            builder.RequireInitialAlignment(_type.GCStaticFieldAlignment.AsInt);

            int staticOffset    = startOffset;
            int staticOffsetEnd = _type.GCStaticFieldSize.AsInt;
            int idx             = 0;

            while (staticOffset < staticOffsetEnd)
            {
                int writeTo = staticOffsetEnd;
                if (idx < sortedPreInitFields.Count)
                {
                    writeTo = sortedPreInitFields[idx].Field.Offset.AsInt;
                }

                // Emit the zero before the next preinitField
                builder.EmitZeros(writeTo - staticOffset);
                staticOffset = writeTo;

                // Emit a pointer reloc to the frozen data
                if (idx < sortedPreInitFields.Count)
                {
                    builder.EmitPointerReloc(factory.SerializedFrozenArray(sortedPreInitFields[idx]));
                    idx++;
                    staticOffset += factory.Target.PointerSize;
                }
            }

            builder.AddSymbol(node);

            return(builder.ToObjectData());
        }
Example #5
0
        public void EmitPortableExecutable()
        {
            bool succeeded = false;

            try
            {
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();

                PEHeaderBuilder headerBuilder;
                int?            timeDateStamp;
                ISymbolNode     r2rHeaderExportSymbol;
                Func <IEnumerable <Blob>, BlobContentId> peIdProvider = null;

                if (_nodeFactory.CompilationModuleGroup.IsCompositeBuildMode && _componentModule == null)
                {
                    headerBuilder = PEHeaderProvider.Create(
                        imageCharacteristics: Characteristics.ExecutableImage | Characteristics.Dll,
                        dllCharacteristics: default(DllCharacteristics),
                        Subsystem.Unknown,
                        _nodeFactory.Target);
                    peIdProvider          = new Func <IEnumerable <Blob>, BlobContentId>(content => BlobContentId.FromHash(CryptographicHashProvider.ComputeSourceHash(content)));
                    timeDateStamp         = null;
                    r2rHeaderExportSymbol = _nodeFactory.Header;
                }
                else
                {
                    PEReader inputPeReader = (_componentModule != null ? _componentModule.PEReader : _nodeFactory.CompilationModuleGroup.CompilationModuleSet.First().PEReader);
                    headerBuilder         = PEHeaderProvider.Copy(inputPeReader.PEHeaders, _nodeFactory.Target);
                    timeDateStamp         = inputPeReader.PEHeaders.CoffHeader.TimeDateStamp;
                    r2rHeaderExportSymbol = null;
                }

                Func <RuntimeFunctionsTableNode> getRuntimeFunctionsTable = null;
                if (_componentModule == null)
                {
                    getRuntimeFunctionsTable = GetRuntimeFunctionsTable;
                }
                R2RPEBuilder r2rPeBuilder = new R2RPEBuilder(
                    _nodeFactory.Target,
                    headerBuilder,
                    r2rHeaderExportSymbol,
                    Path.GetFileName(_objectFilePath),
                    getRuntimeFunctionsTable,
                    _customPESectionAlignment,
                    peIdProvider);

                NativeDebugDirectoryEntryNode nativeDebugDirectoryEntryNode = null;
                ISymbolDefinitionNode         firstImportThunk = null;
                ISymbolDefinitionNode         lastImportThunk  = null;
                ObjectNode lastWrittenObjectNode = null;

                int nodeIndex = -1;
                foreach (var depNode in _nodes)
                {
                    ++nodeIndex;
                    ObjectNode node = depNode as ObjectNode;

                    if (node == null)
                    {
                        continue;
                    }

                    if (node.ShouldSkipEmittingObjectNode(_nodeFactory))
                    {
                        continue;
                    }

                    ObjectData nodeContents = node.GetData(_nodeFactory);

                    if (node is NativeDebugDirectoryEntryNode nddeNode)
                    {
                        // There should be only one NativeDebugDirectoryEntry.
                        Debug.Assert(nativeDebugDirectoryEntryNode == null);
                        nativeDebugDirectoryEntryNode = nddeNode;
                    }

                    if (node is ImportThunk importThunkNode)
                    {
                        Debug.Assert(firstImportThunk == null || lastWrittenObjectNode is ImportThunk,
                                     "All the import thunks must be in single contiguous run");

                        if (firstImportThunk == null)
                        {
                            firstImportThunk = importThunkNode;
                        }
                        lastImportThunk = importThunkNode;
                    }

                    string name = null;

                    if (_mapFileBuilder != null)
                    {
                        name = depNode.GetType().ToString();
                        int firstGeneric = name.IndexOf('[');
                        if (firstGeneric < 0)
                        {
                            firstGeneric = name.Length;
                        }
                        int lastDot = name.LastIndexOf('.', firstGeneric - 1, firstGeneric);
                        if (lastDot > 0)
                        {
                            name = name.Substring(lastDot + 1);
                        }
                    }

                    EmitObjectData(r2rPeBuilder, nodeContents, nodeIndex, name, node.Section);
                    lastWrittenObjectNode = node;

                    if ((_generatePdbFile || _generatePerfMapFile) && node is MethodWithGCInfo methodNode)
                    {
                        _outputInfoBuilder.AddMethod(methodNode, nodeContents.DefinedSymbols[0]);
                    }
                }

                r2rPeBuilder.SetCorHeader(_nodeFactory.CopiedCorHeaderNode, _nodeFactory.CopiedCorHeaderNode.Size);
                r2rPeBuilder.SetDebugDirectory(_nodeFactory.DebugDirectoryNode, _nodeFactory.DebugDirectoryNode.Size);
                if (firstImportThunk != null)
                {
                    r2rPeBuilder.AddSymbolForRange(_nodeFactory.DelayLoadMethodCallThunks, firstImportThunk, lastImportThunk);
                }


                if (_nodeFactory.Win32ResourcesNode != null)
                {
                    Debug.Assert(_nodeFactory.Win32ResourcesNode.Size != 0);
                    r2rPeBuilder.SetWin32Resources(_nodeFactory.Win32ResourcesNode, _nodeFactory.Win32ResourcesNode.Size);
                }

                using (var peStream = File.Create(_objectFilePath))
                {
                    r2rPeBuilder.Write(peStream, timeDateStamp);

                    if (_mapFileBuilder != null)
                    {
                        _mapFileBuilder.SetFileSize(peStream.Length);
                    }

                    // Compute MD5 hash of the output image and store that in the native DebugDirectory entry
                    using (var md5Hash = MD5.Create())
                    {
                        peStream.Seek(0, SeekOrigin.Begin);
                        byte[] hash      = md5Hash.ComputeHash(peStream);
                        byte[] rsdsEntry = nativeDebugDirectoryEntryNode.GenerateRSDSEntryData(hash);

                        int offsetToUpdate = r2rPeBuilder.GetSymbolFilePosition(nativeDebugDirectoryEntryNode);
                        peStream.Seek(offsetToUpdate, SeekOrigin.Begin);
                        peStream.Write(rsdsEntry);
                    }
                }

                if (_outputInfoBuilder != null)
                {
                    r2rPeBuilder.AddSections(_outputInfoBuilder);

                    if (_generateMapFile)
                    {
                        string mapFileName = Path.ChangeExtension(_objectFilePath, ".map");
                        _mapFileBuilder.SaveMap(mapFileName);
                    }

                    if (_generateMapCsvFile)
                    {
                        string nodeStatsCsvFileName = Path.ChangeExtension(_objectFilePath, ".nodestats.csv");
                        string mapCsvFileName       = Path.ChangeExtension(_objectFilePath, ".map.csv");
                        _mapFileBuilder.SaveCsv(nodeStatsCsvFileName, mapCsvFileName);
                    }

                    if (_generatePdbFile)
                    {
                        string path = _pdbPath;
                        if (string.IsNullOrEmpty(path))
                        {
                            path = Path.GetDirectoryName(_objectFilePath);
                        }
                        _symbolFileBuilder.SavePdb(path, _objectFilePath);
                    }

                    if (_generatePerfMapFile)
                    {
                        string path = _perfMapPath;
                        if (string.IsNullOrEmpty(path))
                        {
                            path = Path.GetDirectoryName(_objectFilePath);
                        }
                        _symbolFileBuilder.SavePerfMap(path, _objectFilePath);
                    }

                    if (_profileFileBuilder != null)
                    {
                        string path = Path.ChangeExtension(_objectFilePath, ".profile");
                        _profileFileBuilder.SaveProfile(path);
                    }
                }

                succeeded = true;
            }
            finally
            {
                if (!succeeded)
                {
                    // If there was an exception while generating the OBJ file, make sure we don't leave the unfinished
                    // object file around.
                    try
                    {
                        File.Delete(_objectFilePath);
                    }
                    catch
                    {
                    }
                }
            }
        }
Example #6
0
 public void AddSymbol(ISymbolDefinitionNode symbol)
 {
     _builder.AddSymbol(symbol);
 }
 public void AddSymbol(ISymbolDefinitionNode node)
 {
     _definedSymbols.Add(node);
 }
Example #8
0
 public void AddMethod(MethodWithGCInfo method, ISymbolDefinitionNode symbol)
 {
     _methodSymbolMap.Add(symbol, method);
 }
Example #9
0
 public void AddNode(OutputNode node, ISymbolDefinitionNode symbol)
 {
     _nodes.Add(node);
     _nodeSymbolMap.Add(symbol, node);
 }