Пример #1
0
        protected override string GetName(NodeFactory factory)
        {
            Utf8StringBuilder sb = new Utf8StringBuilder();

            AppendMangledName(factory.NameMangler, sb);
            return(sb.ToString());
        }
Пример #2
0
        protected override void DumpObjectNode(NameMangler mangler, ObjectNode node, ObjectData objectData)
        {
            string name = null;

            _writer.WriteStartElement(GetObjectNodeName(node));

            var symbolNode = node as ISymbolNode;

            if (symbolNode != null)
            {
                Utf8StringBuilder sb = new Utf8StringBuilder();
                symbolNode.AppendMangledName(mangler, sb);
                name = sb.ToString();
                _writer.WriteAttributeString("Name", name);
            }

            _writer.WriteAttributeString("Length", objectData.Data.Length.ToStringInvariant());
            _writer.WriteAttributeString("Hash", HashData(objectData.Data));
            _writer.WriteEndElement();

            var nodeWithCodeInfo = node as INodeWithCodeInfo;

            if (nodeWithCodeInfo != null)
            {
                _writer.WriteStartElement("GCInfo");
                _writer.WriteAttributeString("Name", name);
                _writer.WriteAttributeString("Length", nodeWithCodeInfo.GCInfo.Length.ToStringInvariant());
                _writer.WriteAttributeString("Hash", HashData(nodeWithCodeInfo.GCInfo));
                _writer.WriteEndElement();
            }
        }
Пример #3
0
        protected override string GetName(NodeFactory context)
        {
            Utf8StringBuilder sb = new Utf8StringBuilder();

            sb.Append("ProfileDataNode->");
            _methodNode.AppendMangledName(context.NameMangler, sb);
            return(sb.ToString());
        }
Пример #4
0
        public void TestUtfStringBuilder2()
        {
            string            source = "abcd012345\n\r\u0000\u00a4\u10fb\ufffdnjetty";
            Utf8StringBuilder buffer = new Utf8StringBuilder();

            buffer.Append(source);

            for (int i = 0; i < 100; i++)
            {
                source += "abcd012345\n\r\u0000\u00a4\u10fb\ufffdnjetty";
                buffer.Append("abcd012345\n\r\u0000\u00a4\u10fb\ufffdnjetty");
            }



            Assert.AreEqual(source, buffer.ToString());
            Assert.IsTrue(buffer.ToString().EndsWith("njetty"));
        }
Пример #5
0
        /// <summary>
        /// Add an ObjectData block to a given section.
        /// </summary>
        /// <param name="data">Block to add</param>
        /// <param name="sectionIndex">Section index</param>
        /// <param name="name">Node name to emit in the map file</param>
        /// <param name="mapFile">Optional map file to emit</param>
        public void AddObjectData(ObjectNode.ObjectData objectData, int sectionIndex, string name, TextWriter mapFile)
        {
            Section section = _sections[sectionIndex];

            // Calculate alignment padding - apparently ObjectDataBuilder can produce an alignment of 0
            int alignedOffset = section.Content.Count;

            if (objectData.Alignment > 1)
            {
                alignedOffset = (section.Content.Count + objectData.Alignment - 1) & -objectData.Alignment;
                int padding = alignedOffset - section.Content.Count;
                if (padding > 0)
                {
                    byte paddingByte = 0;
                    if ((section.Characteristics & SectionCharacteristics.ContainsCode) != 0)
                    {
                        // TODO: only use INT3 on x86 & amd64
                        paddingByte = 0xCC;
                    }

                    section.Content.WriteBytes(paddingByte, padding);
                }
            }

            if (mapFile != null)
            {
                mapFile.WriteLine($@"S{sectionIndex}+0x{alignedOffset:X4}..{(alignedOffset + objectData.Data.Length):X4}: {objectData.Data.Length:X4} * {name}");
            }

            section.Content.WriteBytes(objectData.Data);

            if (objectData.DefinedSymbols != null)
            {
                foreach (ISymbolDefinitionNode symbol in objectData.DefinedSymbols)
                {
                    if (mapFile != null)
                    {
                        Utf8StringBuilder sb = new Utf8StringBuilder();
                        symbol.AppendMangledName(GetNameMangler(), sb);
                        int sectionRelativeOffset = alignedOffset + symbol.Offset;
                        mapFile.WriteLine($@"  +0x{sectionRelativeOffset:X4}: {sb.ToString()}");
                    }
                    _symbolMap.Add(symbol, new SymbolTarget(
                                       sectionIndex: sectionIndex,
                                       offset: alignedOffset + symbol.Offset));
                }
            }

            if (objectData.Relocs != null && objectData.Relocs.Length != 0)
            {
                section.Relocations.Add(new ObjectDataRelocations(alignedOffset, objectData.Relocs));
            }
        }
Пример #6
0
        public void TestUtfStringBuilder1()
        {
            string source = "abcd012345\n\r\u0000\u00a4\u10fb\ufffdnjetty";

            for (int i = 0; i < 100; i++)
            {
                source += "abcd012345\n\r\u0000\u00a4\u10fb\ufffdnjetty";
            }

            byte[]            bytes  = System.Text.Encoding.UTF8.GetBytes(source);
            Utf8StringBuilder buffer = new Utf8StringBuilder();

            for (int i = 0; i < bytes.Length; i++)
            {
                buffer.Append(bytes[i]);
            }


            Assert.AreEqual(source, buffer.ToString());
            Assert.IsTrue(buffer.ToString().EndsWith("njetty"));
        }
Пример #7
0
        /// <summary>
        /// Add an ObjectData block to a given section.
        /// </summary>
        /// <param name="data">Block to add</param>
        /// <param name="sectionIndex">Section index</param>
        /// <param name="name">Node name to emit in the map file</param>
        /// <param name="mapFileBuilder">Optional map file to emit</param>
        public void AddObjectData(ObjectNode.ObjectData objectData, int sectionIndex, string name, MapFileBuilder mapFileBuilder)
        {
            Section section = _sections[sectionIndex];

            // Calculate alignment padding - apparently ObjectDataBuilder can produce an alignment of 0
            int alignedOffset = section.Content.Count;

            if (objectData.Alignment > 1)
            {
                alignedOffset = (section.Content.Count + objectData.Alignment - 1) & -objectData.Alignment;
                int padding = alignedOffset - section.Content.Count;
                if (padding > 0)
                {
                    if ((section.Characteristics & SectionCharacteristics.ContainsCode) != 0)
                    {
                        uint cp = _codePadding;
                        while (padding >= sizeof(uint))
                        {
                            section.Content.WriteUInt32(cp);
                            padding -= sizeof(uint);
                        }
                        if (padding >= 2)
                        {
                            section.Content.WriteUInt16(unchecked ((ushort)cp));
                            cp >>= 16;
                        }
                        if ((padding & 1) != 0)
                        {
                            section.Content.WriteByte(unchecked ((byte)cp));
                        }
                    }
                    else
                    {
                        section.Content.WriteBytes(0, padding);
                    }
                }
            }

            if (mapFileBuilder != null)
            {
                MapFileNode node = new MapFileNode(sectionIndex, alignedOffset, objectData.Data.Length, name);
                mapFileBuilder.AddNode(node);
                if (objectData.Relocs != null)
                {
                    foreach (Relocation reloc in objectData.Relocs)
                    {
                        RelocType fileReloc = Relocation.GetFileRelocationType(reloc.RelocType);
                        if (fileReloc != RelocType.IMAGE_REL_BASED_ABSOLUTE)
                        {
                            mapFileBuilder.AddRelocation(node, fileReloc);
                        }
                    }
                }
            }

            section.Content.WriteBytes(objectData.Data);

            if (objectData.DefinedSymbols != null)
            {
                foreach (ISymbolDefinitionNode symbol in objectData.DefinedSymbols)
                {
                    if (mapFileBuilder != null)
                    {
                        Utf8StringBuilder sb = new Utf8StringBuilder();
                        symbol.AppendMangledName(GetNameMangler(), sb);
                        int sectionRelativeOffset = alignedOffset + symbol.Offset;
                        mapFileBuilder.AddSymbol(new MapFileSymbol(sectionIndex, sectionRelativeOffset, sb.ToString()));
                    }
                    _symbolMap.Add(symbol, new SymbolTarget(
                                       sectionIndex: sectionIndex,
                                       offset: alignedOffset + symbol.Offset,
                                       size: objectData.Data.Length));
                }
            }

            if (objectData.Relocs != null && objectData.Relocs.Length != 0)
            {
                section.PlacedObjectDataToRelocate.Add(new PlacedObjectData(alignedOffset, objectData));
            }
        }
Пример #8
0
        /// <summary>
        /// Add an ObjectData block to a given section.
        /// </summary>
        /// <param name="data">Block to add</param>
        /// <param name="sectionIndex">Section index</param>
        /// <param name="name">Node name to emit in the map file</param>
        /// <param name="mapFile">Optional map file to emit</param>
        public void AddObjectData(ObjectNode.ObjectData objectData, int sectionIndex, string name, TextWriter mapFile)
        {
            Section section = _sections[sectionIndex];

            // Calculate alignment padding - apparently ObjectDataBuilder can produce an alignment of 0
            int alignedOffset = section.Content.Count;

            if (objectData.Alignment > 1)
            {
                alignedOffset = (section.Content.Count + objectData.Alignment - 1) & -objectData.Alignment;
                int padding = alignedOffset - section.Content.Count;
                if (padding > 0)
                {
                    if ((section.Characteristics & SectionCharacteristics.ContainsCode) != 0)
                    {
                        uint cp = _codePadding;
                        while (padding >= sizeof(uint))
                        {
                            section.Content.WriteUInt32(cp);
                            padding -= sizeof(uint);
                        }
                        if (padding >= 2)
                        {
                            section.Content.WriteUInt16(unchecked ((ushort)cp));
                            cp >>= 16;
                        }
                        if ((padding & 1) != 0)
                        {
                            section.Content.WriteByte(unchecked ((byte)cp));
                        }
                    }
                    else
                    {
                        section.Content.WriteBytes(0, padding);
                    }
                }
            }

            if (mapFile != null)
            {
                mapFile.WriteLine($@"S{sectionIndex}+0x{alignedOffset:X4}..{(alignedOffset + objectData.Data.Length):X4}: {objectData.Data.Length:X4} * {name}");
            }

            section.Content.WriteBytes(objectData.Data);

            if (objectData.DefinedSymbols != null)
            {
                foreach (ISymbolDefinitionNode symbol in objectData.DefinedSymbols)
                {
                    if (mapFile != null)
                    {
                        Utf8StringBuilder sb = new Utf8StringBuilder();
                        symbol.AppendMangledName(GetNameMangler(), sb);
                        int sectionRelativeOffset = alignedOffset + symbol.Offset;
                        mapFile.WriteLine($@"  +0x{sectionRelativeOffset:X4}: {sb.ToString()}");
                    }
                    _symbolMap.Add(symbol, new SymbolTarget(
                                       sectionIndex: sectionIndex,
                                       offset: alignedOffset + symbol.Offset));
                }
            }

            if (objectData.Relocs != null && objectData.Relocs.Length != 0)
            {
                section.PlacedObjectDataToRelocate.Add(new PlacedObjectData(alignedOffset, objectData));
            }
        }
Пример #9
0
        public void PublishUnwindInfo(ObjectNode node)
        {
            INodeWithCodeInfo nodeWithCodeInfo = node as INodeWithCodeInfo;

            if (nodeWithCodeInfo == null)
            {
                return;
            }

            FrameInfo[] frameInfos = nodeWithCodeInfo.FrameInfos;
            if (frameInfos == null)
            {
                // Data should only be present if the method has unwind info
                Debug.Assert(nodeWithCodeInfo.GetAssociatedDataNode(_nodeFactory) == null);

                return;
            }

            byte[]      gcInfo             = nodeWithCodeInfo.GCInfo;
            ObjectData  ehInfo             = nodeWithCodeInfo.EHInfo;
            ISymbolNode associatedDataNode = nodeWithCodeInfo.GetAssociatedDataNode(_nodeFactory);

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

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

                ObjectNodeSection section = ObjectNodeSection.XDataSection;
                if (ShouldShareSymbol(node))
                {
                    section = GetSharedSection(section, _sb.ToString());
                }
                SwitchSection(_nativeObjectWriter, section.Name, GetCustomSectionAttributes(section), section.ComdatName);

                EmitAlignment(4);
                EmitSymbolDef(blobSymbolName);

                FrameInfoFlags flags = frameInfo.Flags;
                flags |= ehInfo != null ? FrameInfoFlags.HasEHInfo : 0;
                flags |= associatedDataNode != null ? FrameInfoFlags.HasAssociatedData : 0;

                EmitBlob(blob);

                EmitIntValue((byte)flags, 1);

                if (associatedDataNode != null)
                {
                    EmitSymbolRef(_sb.Clear().Append(associatedDataNode.GetMangledName(_nodeFactory.NameMangler)), RelocType.IMAGE_REL_BASED_ABSOLUTE);
                    associatedDataNode = null;
                }

                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();
            }
        }
Пример #10
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("_unwind").Append(i.ToStringInvariant());

                    ObjectNodeSection section = ObjectNodeSection.XDataSection;
                    if (node.ShouldShareNodeAcrossModules(factory) && factory.Target.OperatingSystem == TargetOS.Windows)
                    {
                        section = section.GetSharedSection(_sb.ToString());
                        CreateCustomSection(section);
                    }
                    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("_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;
                    }

                    // 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
                {
                    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();
            }
        }