Esempio n. 1
0
        public static void EmitObject(string objectFilePath, IEnumerable <DependencyNode> nodes, NodeFactory factory, IObjectDumper dumper)
        {
            ObjectWriter objectWriter = new ObjectWriter(objectFilePath, factory);
            bool         succeeded    = false;

            try
            {
                ObjectNodeSection managedCodeSection;
                if (factory.Target.OperatingSystem == TargetOS.Windows)
                {
                    managedCodeSection = MethodCodeNode.WindowsContentSection;

                    // Emit sentinels for managed code section.
                    ObjectNodeSection codeStartSection = factory.CompilationModuleGroup.IsSingleFileCompilation ?
                                                         MethodCodeNode.StartSection :
                                                         MethodCodeNode.StartSection.GetSharedSection("__managedcode_a");
                    objectWriter.SetSection(codeStartSection);
                    objectWriter.EmitSymbolDef(new Utf8StringBuilder().Append("__managedcode_a"));
                    objectWriter.EmitIntValue(0, 1);
                    ObjectNodeSection codeEndSection = factory.CompilationModuleGroup.IsSingleFileCompilation ?
                                                       MethodCodeNode.EndSection :
                                                       MethodCodeNode.EndSection.GetSharedSection("__managedcode_z");
                    objectWriter.SetSection(codeEndSection);
                    objectWriter.EmitSymbolDef(new Utf8StringBuilder().Append("__managedcode_z"));
                    objectWriter.EmitIntValue(1, 1);
                }
                else
                {
                    managedCodeSection = MethodCodeNode.UnixContentSection;
                    // TODO 2916: managed code section has to be created here, switch is not necessary.
                    objectWriter.SetSection(MethodCodeNode.UnixContentSection);
                    objectWriter.SetSection(LsdaSection);
                }
                objectWriter.SetCodeSectionAttribute(managedCodeSection);

                // Build file info map.
                objectWriter.BuildFileInfoMap(nodes);

                foreach (DependencyNode depNode in nodes)
                {
                    ObjectNode node = depNode as ObjectNode;
                    if (node == null)
                    {
                        continue;
                    }

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

                    ObjectData nodeContents = node.GetData(factory);

                    if (dumper != null)
                    {
                        dumper.DumpObjectNode(factory.NameMangler, node, nodeContents);
                    }

#if DEBUG
                    foreach (ISymbolNode definedSymbol in nodeContents.DefinedSymbols)
                    {
                        try
                        {
                            _previouslyWrittenNodeNames.Add(definedSymbol.GetMangledName(factory.NameMangler), definedSymbol);
                        }
                        catch (ArgumentException)
                        {
                            ISymbolNode alreadyWrittenSymbol = _previouslyWrittenNodeNames[definedSymbol.GetMangledName(factory.NameMangler)];
                            Debug.Assert(false, "Duplicate node name emitted to file",
                                         $"Symbol {definedSymbol.GetMangledName(factory.NameMangler)} has already been written to the output object file {objectFilePath} with symbol {alreadyWrittenSymbol}");
                        }
                    }
#endif


                    ObjectNodeSection section = node.Section;
                    if (objectWriter.ShouldShareSymbol(node))
                    {
                        section = section.GetSharedSection(((ISymbolNode)node).GetMangledName(factory.NameMangler));
                    }

                    // Ensure section and alignment for the node.
                    objectWriter.SetSection(section);
                    objectWriter.EmitAlignment(nodeContents.Alignment);

                    // Build symbol definition map.
                    objectWriter.BuildSymbolDefinitionMap(node, nodeContents.DefinedSymbols);

                    if (!factory.Target.IsWindows)
                    {
                        objectWriter.BuildCFIMap(factory, node);
                    }

                    // Build debug location map
                    objectWriter.BuildDebugLocInfoMap(node);

                    Relocation[] relocs          = nodeContents.Relocs;
                    int          nextRelocOffset = -1;
                    int          nextRelocIndex  = -1;
                    if (relocs.Length > 0)
                    {
                        nextRelocOffset = relocs[0].Offset;
                        nextRelocIndex  = 0;
                    }

                    int i = 0;
                    while (i < nodeContents.Data.Length)
                    {
                        // Emit symbol definitions if necessary
                        objectWriter.EmitSymbolDefinition(i);

                        // Emit CFI codes for the given offset.
                        objectWriter.EmitCFICodes(i);

                        // Emit debug loc info if needed.
                        objectWriter.EmitDebugLocInfo(i);

                        if (i == nextRelocOffset)
                        {
                            Relocation reloc = relocs[nextRelocIndex];

                            long delta;
                            unsafe
                            {
                                fixed(void *location = &nodeContents.Data[i])
                                {
                                    delta = Relocation.ReadValue(reloc.RelocType, location);
                                }
                            }
                            int size = objectWriter.EmitSymbolReference(reloc.Target, (int)delta, reloc.RelocType);

                            // Update nextRelocIndex/Offset
                            if (++nextRelocIndex < relocs.Length)
                            {
                                nextRelocOffset = relocs[nextRelocIndex].Offset;
                            }
                            else
                            {
                                // This is the last reloc. Set the next reloc offset to -1 in case the last reloc has a zero size,
                                // which means the reloc does not have vacant bytes corresponding to in the data buffer. E.g,
                                // IMAGE_REL_THUMB_BRANCH24 is a kind of 24-bit reloc whose bits scatte over the instruction that
                                // references it. We do not vacate extra bytes in the data buffer for this kind of reloc.
                                nextRelocOffset = -1;
                            }
                            i += size;
                        }
                        else
                        {
                            objectWriter.EmitIntValue(nodeContents.Data[i], 1);
                            i++;
                        }
                    }

                    // It is possible to have a symbol just after all of the data.
                    objectWriter.EmitSymbolDefinition(nodeContents.Data.Length);

                    // Publish Windows unwind info.
                    if (factory.Target.IsWindows)
                    {
                        objectWriter.PublishUnwindInfo(node);
                    }

                    // Emit the last CFI to close the frame.
                    objectWriter.EmitCFICodes(nodeContents.Data.Length);

                    if (objectWriter.HasFunctionDebugInfo())
                    {
                        // Build debug local var info
                        objectWriter.EmitDebugVarInfo(node);

                        objectWriter.EmitDebugFunctionInfo(nodeContents.Data.Length);
                    }
                }

                objectWriter.EmitDebugModuleInfo();

                succeeded = true;
            }
            finally
            {
                objectWriter.Dispose();

                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
                    {
                    }
                }
            }
        }
Esempio n. 2
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;
            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;

                ObjectNodeSection lsdaSection = LsdaSection;
                if (ShouldShareSymbol(node))
                {
                    lsdaSection = lsdaSection.GetSharedSection(((ISymbolNode)node).GetMangledName(_nodeFactory.NameMangler));
                }
                SwitchSection(_nativeObjectWriter, lsdaSection.Name, GetCustomSectionAttributes(lsdaSection), lsdaSection.ComdatName);

                _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();
        }
Esempio n. 3
0
        public static void EmitObject(string objectFilePath, IEnumerable <DependencyNode> nodes, NodeFactory factory)
        {
            using (ObjectWriter objectWriter = new ObjectWriter(objectFilePath, factory))
            {
                // TODO: Exception handling on Unix
                if (factory.Target.IsWindows)
                {
                    objectWriter.CreateCustomSection(MethodCodeNode.ContentSection);

                    // Emit sentinels for managed code section.
                    ObjectNodeSection codeStartSection = factory.CompilationModuleGroup.IsSingleFileCompilation ? MethodCodeNode.StartSection : MethodCodeNode.StartSection.GetSharedSection("__managedcode_a");
                    objectWriter.SetSection(codeStartSection);
                    objectWriter.EmitSymbolDef("__managedcode_a");
                    objectWriter.EmitIntValue(0, 1);
                    ObjectNodeSection codeEndSection = factory.CompilationModuleGroup.IsSingleFileCompilation ? MethodCodeNode.EndSection : MethodCodeNode.EndSection.GetSharedSection("__managedcode_z");
                    objectWriter.SetSection(codeEndSection);
                    objectWriter.EmitSymbolDef("__managedcode_z");
                    objectWriter.EmitIntValue(0, 1);
                }

                // Build file info map.
                objectWriter.BuildFileInfoMap(nodes);

                foreach (DependencyNode depNode in nodes)
                {
                    ObjectNode node = depNode as ObjectNode;
                    if (node == null)
                    {
                        continue;
                    }

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

#if DEBUG
                    Debug.Assert(_previouslyWrittenNodeNames.Add(node.GetName()), "Duplicate node name emitted to file", "Node {0} has already been written to the output object file {1}", node.GetName(), objectFilePath);
#endif
                    ObjectNode.ObjectData nodeContents = node.GetData(factory);

                    ObjectNodeSection section = node.Section;
                    if (node.ShouldShareNodeAcrossModules(factory) && factory.Target.OperatingSystem == TargetOS.Windows)
                    {
                        Debug.Assert(node is ISymbolNode);
                        section = section.GetSharedSection(((ISymbolNode)node).MangledName);
                    }

                    // Ensure section and alignment for the node.
                    objectWriter.SetSection(section);
                    objectWriter.EmitAlignment(nodeContents.Alignment);

                    // Build symbol definition map.
                    objectWriter.BuildSymbolDefinitionMap(node, nodeContents.DefinedSymbols);

                    // Build CFI map (Unix) or publish unwind blob (Windows).
                    objectWriter.BuildCFIMap(factory, node);

                    // Build debug location map
                    objectWriter.BuildDebugLocInfoMap(node);

                    Relocation[] relocs          = nodeContents.Relocs;
                    int          nextRelocOffset = -1;
                    int          nextRelocIndex  = -1;
                    if (relocs.Length > 0)
                    {
                        nextRelocOffset = relocs[0].Offset;
                        nextRelocIndex  = 0;
                    }

                    int i = 0;
                    while (i < nodeContents.Data.Length)
                    {
                        // Emit symbol definitions if necessary
                        objectWriter.EmitSymbolDefinition(i);

                        // Emit CFI codes for the given offset.
                        objectWriter.EmitCFICodes(i);

                        // Emit debug loc info if needed.
                        objectWriter.EmitDebugLocInfo(i);

                        if (i == nextRelocOffset)
                        {
                            Relocation reloc = relocs[nextRelocIndex];

                            int size = objectWriter.EmitSymbolReference(reloc.Target, reloc.Delta, reloc.RelocType);

                            // Update nextRelocIndex/Offset
                            if (++nextRelocIndex < relocs.Length)
                            {
                                nextRelocOffset = relocs[nextRelocIndex].Offset;
                            }
                            i += size;
                        }
                        else
                        {
                            objectWriter.EmitIntValue(nodeContents.Data[i], 1);
                            i++;
                        }
                    }

                    // It is possible to have a symbol just after all of the data.
                    objectWriter.EmitSymbolDefinition(nodeContents.Data.Length);

                    // Emit the last CFI to close the frame.
                    objectWriter.EmitCFICodes(nodeContents.Data.Length);

                    if (objectWriter.HasFunctionDebugInfo())
                    {
                        // Build debug local var info
                        objectWriter.EmitDebugVarInfo(node);

                        objectWriter.EmitDebugFunctionInfo(nodeContents.Data.Length);
                    }
                }

                objectWriter.EmitDebugModuleInfo();
            }
        }
Esempio n. 4
0
        public void BuildCFIMap(NodeFactory factory, ObjectNode node)
        {
            _offsetToCfis.Clear();
            _offsetToCfiStart.Clear();
            _offsetToCfiEnd.Clear();
            _frameOpened = false;

            INodeWithCodeInfo nodeWithCodeInfo = node as INodeWithCodeInfo;

            if (nodeWithCodeInfo == null)
            {
                return;
            }

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

            ObjectNode.ObjectData ehInfo = nodeWithCodeInfo.EHInfo;

            int i = 0;

            foreach (var frameInfo in frameInfos)
            {
                int    start = frameInfo.StartOffset;
                int    end   = frameInfo.EndOffset;
                int    len   = frameInfo.BlobData.Length;
                byte[] blob  = frameInfo.BlobData;

                if (_targetPlatform.OperatingSystem == TargetOS.Windows)
                {
                    string blobSymbolName = "_unwind" + (i++).ToStringInvariant() + _currentNodeName;

                    ObjectNodeSection section = ObjectNodeSection.XDataSection;
                    if (node.ShouldShareNodeAcrossModules(factory) && factory.Target.OperatingSystem == TargetOS.Windows)
                    {
                        section = section.GetSharedSection(blobSymbolName);
                        CreateCustomSection(section);
                    }
                    SwitchSection(_nativeObjectWriter, section.Name);

                    EmitAlignment(4);
                    EmitSymbolDef(blobSymbolName);

                    if (ehInfo != null)
                    {
                        blob[blob.Length - 1] |= 0x04; // Flag to indicate that EHClauses follows
                    }

                    EmitBlob(blob);

                    if (ehInfo != null)
                    {
                        Debug.Assert(ehInfo.Alignment == 1);
                        Debug.Assert(ehInfo.DefinedSymbols.Length == 0);
                        EmitBlobWithRelocs(ehInfo.Data, ehInfo.Relocs);
                        ehInfo = null;
                    }

                    // TODO: Currently we get linker errors if we emit frame info for shared types.
                    //       This needs follow-up investigation.
                    if (!node.ShouldShareNodeAcrossModules(factory))
                    {
                        // For window, just emit the frame blob (UNWIND_INFO) as a whole.
                        EmitWinFrameInfo(start, end, len, blobSymbolName);
                    }

                    EnsureCurrentSection();
                }
                else
                {
                    // 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);
                    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);
                    }
                }
            }
        }
Esempio n. 5
0
        public static void EmitObject(string objectFilePath, IEnumerable <DependencyNode> nodes, NodeFactory factory)
        {
            ObjectWriter objectWriter = new ObjectWriter(objectFilePath, factory);
            bool         succeeded    = false;

            try
            {
                if (factory.Target.OperatingSystem == TargetOS.Windows)
                {
                    objectWriter.CreateCustomSection(MethodCodeNode.WindowsContentSection);

                    // Emit sentinels for managed code section.
                    ObjectNodeSection codeStartSection = factory.CompilationModuleGroup.IsSingleFileCompilation ?
                                                         MethodCodeNode.StartSection :
                                                         MethodCodeNode.StartSection.GetSharedSection("__managedcode_a");
                    objectWriter.SetSection(codeStartSection);
                    objectWriter.EmitSymbolDef(new Utf8StringBuilder().Append("__managedcode_a"));
                    objectWriter.EmitIntValue(0, 1);
                    ObjectNodeSection codeEndSection = factory.CompilationModuleGroup.IsSingleFileCompilation ?
                                                       MethodCodeNode.EndSection :
                                                       MethodCodeNode.EndSection.GetSharedSection("__managedcode_z");
                    objectWriter.SetSection(codeEndSection);
                    objectWriter.EmitSymbolDef(new Utf8StringBuilder().Append("__managedcode_z"));
                    objectWriter.EmitIntValue(0, 1);
                }
                else
                {
                    objectWriter.CreateCustomSection(MethodCodeNode.UnixContentSection);
                    objectWriter.CreateCustomSection(LsdaSection);
                }

                // Build file info map.
                objectWriter.BuildFileInfoMap(nodes);

                foreach (DependencyNode depNode in nodes)
                {
                    ObjectNode node = depNode as ObjectNode;
                    if (node == null)
                    {
                        continue;
                    }

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

                    ObjectNode.ObjectData nodeContents = node.GetData(factory);

#if DEBUG
                    foreach (ISymbolNode definedSymbol in nodeContents.DefinedSymbols)
                    {
                        Debug.Assert(_previouslyWrittenNodeNames.Add(definedSymbol.GetMangledName()), "Duplicate node name emitted to file",
                                     $"Symbol {definedSymbol.GetMangledName()} has already been written to the output object file {objectFilePath}");
                    }
#endif


                    ObjectNodeSection section = node.Section;
                    if (objectWriter.ShouldShareSymbol(node))
                    {
                        section = section.GetSharedSection(((ISymbolNode)node).GetMangledName());
                    }

                    // Ensure section and alignment for the node.
                    objectWriter.SetSection(section);
                    objectWriter.EmitAlignment(nodeContents.Alignment);

                    // Build symbol definition map.
                    objectWriter.BuildSymbolDefinitionMap(node, nodeContents.DefinedSymbols);

                    // Build CFI map (Unix) or publish unwind blob (Windows).
                    objectWriter.BuildCFIMap(factory, node);

                    // Build debug location map
                    objectWriter.BuildDebugLocInfoMap(node);

                    Relocation[] relocs          = nodeContents.Relocs;
                    int          nextRelocOffset = -1;
                    int          nextRelocIndex  = -1;
                    if (relocs.Length > 0)
                    {
                        nextRelocOffset = relocs[0].Offset;
                        nextRelocIndex  = 0;
                    }

                    int i = 0;
                    while (i < nodeContents.Data.Length)
                    {
                        // Emit symbol definitions if necessary
                        objectWriter.EmitSymbolDefinition(i);

                        // Emit CFI codes for the given offset.
                        objectWriter.EmitCFICodes(i);

                        // Emit debug loc info if needed.
                        objectWriter.EmitDebugLocInfo(i);

                        if (i == nextRelocOffset)
                        {
                            Relocation reloc = relocs[nextRelocIndex];

                            long delta;
                            unsafe
                            {
                                fixed(void *location = &nodeContents.Data[i])
                                {
                                    delta = Relocation.ReadValue(reloc.RelocType, location);
                                }
                            }
                            int size = objectWriter.EmitSymbolReference(reloc.Target, (int)delta, reloc.RelocType);

                            // Update nextRelocIndex/Offset
                            if (++nextRelocIndex < relocs.Length)
                            {
                                nextRelocOffset = relocs[nextRelocIndex].Offset;
                            }
                            i += size;
                        }
                        else
                        {
                            objectWriter.EmitIntValue(nodeContents.Data[i], 1);
                            i++;
                        }
                    }

                    // It is possible to have a symbol just after all of the data.
                    objectWriter.EmitSymbolDefinition(nodeContents.Data.Length);

                    // Emit the last CFI to close the frame.
                    objectWriter.EmitCFICodes(nodeContents.Data.Length);

                    if (objectWriter.HasFunctionDebugInfo())
                    {
                        // Build debug local var info
                        objectWriter.EmitDebugVarInfo(node);

                        objectWriter.EmitDebugFunctionInfo(nodeContents.Data.Length);
                    }
                }

                objectWriter.EmitDebugModuleInfo();

                succeeded = true;
            }
            finally
            {
                objectWriter.Dispose();

                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
                    {
                    }
                }
            }
        }
Esempio n. 6
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;
            string mainEhInfoSymbolName  = null;

            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)
                {
                    string blobSymbolName = "_unwind" + i.ToStringInvariant() + _currentNodeName;

                    ObjectNodeSection section = ObjectNodeSection.XDataSection;
                    if (node.ShouldShareNodeAcrossModules(factory) && factory.Target.OperatingSystem == TargetOS.Windows)
                    {
                        section = section.GetSharedSection(blobSymbolName);
                        CreateCustomSection(section);
                    }
                    SwitchSection(_nativeObjectWriter, section.Name);

                    EmitAlignment(4);
                    EmitSymbolDef(blobSymbolName);

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

                    EmitBlob(blob);

                    EmitIntValue((byte)flags, 1);

                    if (ehInfo != null)
                    {
                        mainEhInfoSymbolName = "_ehInfo" + _currentNodeName;
                        EmitSymbolRef(mainEhInfoSymbolName, 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(mainEhInfoSymbolName);
                        EmitBlobWithRelocs(ehInfo.Data, ehInfo.Relocs);
                        ehInfo = null;
                    }

                    // TODO: Currently we get linker errors if we emit frame info for shared types.
                    //       This needs follow-up investigation.
                    if (!node.ShouldShareNodeAcrossModules(factory))
                    {
                        // For window, just emit the frame blob (UNWIND_INFO) as a whole.
                        EmitWinFrameInfo(start, end, len, blobSymbolName);
                    }
                }
                else
                {
                    string blobSymbolName = "_lsda" + i.ToStringInvariant() + _currentNodeName;

                    SwitchSection(_nativeObjectWriter, LsdaSection.Name);

                    EmitSymbolDef(blobSymbolName);

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

                    if (i != 0)
                    {
                        EmitSymbolRef("_lsda0" + _currentNodeName, RelocType.IMAGE_REL_BASED_REL32, 4);

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

                    if (ehInfo != null)
                    {
                        mainEhInfoSymbolName = "_ehInfo" + _currentNodeName;
                        EmitSymbolRef(mainEhInfoSymbolName, 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(mainEhInfoSymbolName);
                        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();
            }
        }