public void BuildSymbolDefinitionMap(ObjectNode node, ISymbolDefinitionNode[] definedSymbols)
        {
            _offsetToDefName.Clear();
            foreach (ISymbolDefinitionNode n in definedSymbols)
            {
                if (!_offsetToDefName.ContainsKey(n.Offset))
                {
                    _offsetToDefName[n.Offset] = new List <ISymbolDefinitionNode>();
                }

                _offsetToDefName[n.Offset].Add(n);
                _byteInterruptionOffsets.Add(n.Offset);
            }

            var symbolNode = node as ISymbolDefinitionNode;

            if (symbolNode != null)
            {
                _sb.Clear();
                AppendExternCPrefix(_sb);
                symbolNode.AppendMangledName(_nodeFactory.NameMangler, _sb);
                _currentNodeZeroTerminatedName = _sb.Append('\0').ToUtf8String();
            }
            else
            {
                _currentNodeZeroTerminatedName = default(Utf8String);
            }
        }
Пример #2
0
        public void PublishUnwindInfo(ObjectNode node)
        {
            INodeWithCodeInfo nodeWithCodeInfo = node as INodeWithCodeInfo;

            if (nodeWithCodeInfo == null)
            {
                return;
            }

            FrameInfo[] frameInfos = nodeWithCodeInfo.FrameInfos;
            if (frameInfos == null)
            {
                return;
            }

            byte[]     gcInfo = nodeWithCodeInfo.GCInfo;
            ObjectData ehInfo = nodeWithCodeInfo.EHInfo;

            for (int i = 0; i < frameInfos.Length; i++)
            {
                FrameInfo frameInfo = frameInfos[i];

                int    start = frameInfo.StartOffset;
                int    end   = frameInfo.EndOffset;
                int    len   = frameInfo.BlobData.Length;
                byte[] blob  = frameInfo.BlobData;

                _sb.Clear().Append(_nodeFactory.NameMangler.CompilationUnitPrefix).Append("_unwind").Append(i.ToStringInvariant());

                ObjectNodeSection section = ObjectNodeSection.XDataSection;
                SwitchSection(_nativeObjectWriter, section.Name);

                byte[] blobSymbolName = _sb.Append(_currentNodeZeroTerminatedName).ToUtf8String().UnderlyingArray;

                EmitAlignment(4);
                EmitSymbolDef(blobSymbolName);

                FrameInfoFlags flags = frameInfo.Flags;
                if (ehInfo != null)
                {
                    flags |= FrameInfoFlags.HasEHInfo;
                }

                EmitBlob(blob);

                EmitIntValue((byte)flags, 1);

                if (ehInfo != null)
                {
                    EmitSymbolRef(_sb.Clear().Append(_nodeFactory.NameMangler.CompilationUnitPrefix).Append("_ehInfo").Append(_currentNodeZeroTerminatedName), RelocType.IMAGE_REL_BASED_ABSOLUTE);
                }

                if (gcInfo != null)
                {
                    EmitBlob(gcInfo);
                    gcInfo = null;
                }

                if (ehInfo != null)
                {
                    // TODO: Place EHInfo into different section for better locality
                    Debug.Assert(ehInfo.Alignment == 1);
                    Debug.Assert(ehInfo.DefinedSymbols.Length == 0);
                    EmitSymbolDef(_sb /* ehInfo */);
                    EmitBlobWithRelocs(ehInfo.Data, ehInfo.Relocs);
                    ehInfo = null;
                }

                // For window, just emit the frame blob (UNWIND_INFO) as a whole.
                EmitWinFrameInfo(start, end, len, blobSymbolName);

                EnsureCurrentSection();
            }
        }
Пример #3
0
        public void BuildCFIMap(NodeFactory factory, ObjectNode node)
        {
            _offsetToCfis.Clear();
            _offsetToCfiStart.Clear();
            _offsetToCfiEnd.Clear();
            _offsetToCfiLsdaBlobName.Clear();
            _frameOpened = false;

            INodeWithCodeInfo nodeWithCodeInfo = node as INodeWithCodeInfo;

            if (nodeWithCodeInfo == null)
            {
                return;
            }

            FrameInfo[] frameInfos = nodeWithCodeInfo.FrameInfos;
            if (frameInfos == null)
            {
                return;
            }

            byte[] gcInfo = nodeWithCodeInfo.GCInfo;
            ObjectNode.ObjectData ehInfo = nodeWithCodeInfo.EHInfo;

            for (int i = 0; i < frameInfos.Length; i++)
            {
                FrameInfo frameInfo = frameInfos[i];

                int    start = frameInfo.StartOffset;
                int    end   = frameInfo.EndOffset;
                int    len   = frameInfo.BlobData.Length;
                byte[] blob  = frameInfo.BlobData;

                if (_targetPlatform.OperatingSystem == TargetOS.Windows)
                {
                    _sb.Clear().Append(NodeFactory.NameMangler.CompilationUnitPrefix).Append("_unwind").Append(i.ToStringInvariant());

                    ObjectNodeSection section = ObjectNodeSection.XDataSection;
                    SwitchSection(_nativeObjectWriter, section.Name);

                    byte[] blobSymbolName = _sb.Append(_currentNodeZeroTerminatedName).ToUtf8String().UnderlyingArray;

                    EmitAlignment(4);
                    EmitSymbolDef(blobSymbolName);

                    FrameInfoFlags flags = frameInfo.Flags;
                    if (ehInfo != null)
                    {
                        flags |= FrameInfoFlags.HasEHInfo;
                    }

                    EmitBlob(blob);

                    EmitIntValue((byte)flags, 1);

                    if (ehInfo != null)
                    {
                        EmitSymbolRef(_sb.Clear().Append(NodeFactory.NameMangler.CompilationUnitPrefix).Append("_ehInfo").Append(_currentNodeZeroTerminatedName), RelocType.IMAGE_REL_BASED_ABSOLUTE);
                    }

                    if (gcInfo != null)
                    {
                        EmitBlob(gcInfo);
                        gcInfo = null;
                    }

                    if (ehInfo != null)
                    {
                        // TODO: Place EHInfo into different section for better locality
                        Debug.Assert(ehInfo.Alignment == 1);
                        Debug.Assert(ehInfo.DefinedSymbols.Length == 0);
                        EmitSymbolDef(_sb /* ehInfo */);
                        EmitBlobWithRelocs(ehInfo.Data, ehInfo.Relocs);
                        ehInfo = null;
                    }

                    // For window, just emit the frame blob (UNWIND_INFO) as a whole.
                    EmitWinFrameInfo(start, end, len, blobSymbolName);
                }
                else
                {
                    SwitchSection(_nativeObjectWriter, LsdaSection.Name);

                    _sb.Clear().Append("_lsda").Append(i.ToStringInvariant()).Append(_currentNodeZeroTerminatedName);
                    byte[] blobSymbolName = _sb.ToUtf8String().UnderlyingArray;
                    EmitSymbolDef(blobSymbolName);

                    FrameInfoFlags flags = frameInfo.Flags;
                    if (ehInfo != null)
                    {
                        flags |= FrameInfoFlags.HasEHInfo;
                    }
                    EmitIntValue((byte)flags, 1);

                    if (i != 0)
                    {
                        EmitSymbolRef(_sb.Clear().Append("_lsda0").Append(_currentNodeZeroTerminatedName), RelocType.IMAGE_REL_BASED_REL32, 4);

                        // emit relative offset from the main function
                        EmitIntValue((ulong)(start - frameInfos[0].StartOffset), 4);
                    }

                    if (ehInfo != null)
                    {
                        EmitSymbolRef(_sb.Clear().Append("_ehInfo").Append(_currentNodeZeroTerminatedName), RelocType.IMAGE_REL_BASED_REL32, 4);
                    }

                    if (gcInfo != null)
                    {
                        EmitBlob(gcInfo);
                        gcInfo = null;
                    }

                    if (ehInfo != null)
                    {
                        // TODO: Place EHInfo into different section for better locality
                        Debug.Assert(ehInfo.Alignment == 1);
                        Debug.Assert(ehInfo.DefinedSymbols.Length == 0);
                        EmitSymbolDef(_sb /* ehInfo */);
                        EmitBlobWithRelocs(ehInfo.Data, ehInfo.Relocs);
                        ehInfo = null;
                    }

                    // For Unix, we build CFI blob map for each offset.
                    Debug.Assert(len % CfiCodeSize == 0);

                    // Record start/end of frames which shouldn't be overlapped.
                    _offsetToCfiStart.Add(start);
                    _offsetToCfiEnd.Add(end);
                    _offsetToCfiLsdaBlobName.Add(start, blobSymbolName);
                    for (int j = 0; j < len; j += CfiCodeSize)
                    {
                        // The first byte of CFI_CODE is offset from the range the frame covers.
                        // Compute code offset from the root method.
                        int           codeOffset = blob[j] + start;
                        List <byte[]> cfis;
                        if (!_offsetToCfis.TryGetValue(codeOffset, out cfis))
                        {
                            cfis = new List <byte[]>();
                            _offsetToCfis.Add(codeOffset, cfis);
                        }
                        byte[] cfi = new byte[CfiCodeSize];
                        Array.Copy(blob, j, cfi, 0, CfiCodeSize);
                        cfis.Add(cfi);
                    }
                }

                EnsureCurrentSection();
            }
        }