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