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