diff --git a/source/Cosmos.sln b/source/Cosmos.sln
index 8b65884c8..3fd42f53a 100644
--- a/source/Cosmos.sln
+++ b/source/Cosmos.sln
@@ -627,7 +627,6 @@ Global
{B2F76E27-EAE1-4ECF-8A33-77B2CFBB9367}.Release|x86.Build.0 = Release|x86
{6658FCE0-7032-4B7B-BD95-F2765C393442}.Bootstrap|Any CPU.ActiveCfg = Release|x86
{6658FCE0-7032-4B7B-BD95-F2765C393442}.Bootstrap|Mixed Platforms.ActiveCfg = Release|x86
- {6658FCE0-7032-4B7B-BD95-F2765C393442}.Bootstrap|Mixed Platforms.Build.0 = Release|x86
{6658FCE0-7032-4B7B-BD95-F2765C393442}.Bootstrap|x86.ActiveCfg = Debug|x86
{6658FCE0-7032-4B7B-BD95-F2765C393442}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6658FCE0-7032-4B7B-BD95-F2765C393442}.Debug|Any CPU.Build.0 = Debug|Any CPU
@@ -709,7 +708,6 @@ Global
{AE684C98-F100-47AE-9C8C-E71BF8C9F8AA}.Bootstrap|Any CPU.ActiveCfg = Release|Any CPU
{AE684C98-F100-47AE-9C8C-E71BF8C9F8AA}.Bootstrap|Any CPU.Build.0 = Release|Any CPU
{AE684C98-F100-47AE-9C8C-E71BF8C9F8AA}.Bootstrap|Mixed Platforms.ActiveCfg = Release|Any CPU
- {AE684C98-F100-47AE-9C8C-E71BF8C9F8AA}.Bootstrap|Mixed Platforms.Build.0 = Release|Any CPU
{AE684C98-F100-47AE-9C8C-E71BF8C9F8AA}.Bootstrap|x86.ActiveCfg = Release|Any CPU
{AE684C98-F100-47AE-9C8C-E71BF8C9F8AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE684C98-F100-47AE-9C8C-E71BF8C9F8AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
@@ -725,7 +723,6 @@ Global
{54795C40-B3E8-4DBB-A3DE-FACBADD20ADB}.Bootstrap|Any CPU.ActiveCfg = Release|Any CPU
{54795C40-B3E8-4DBB-A3DE-FACBADD20ADB}.Bootstrap|Any CPU.Build.0 = Release|Any CPU
{54795C40-B3E8-4DBB-A3DE-FACBADD20ADB}.Bootstrap|Mixed Platforms.ActiveCfg = Release|Any CPU
- {54795C40-B3E8-4DBB-A3DE-FACBADD20ADB}.Bootstrap|Mixed Platforms.Build.0 = Release|Any CPU
{54795C40-B3E8-4DBB-A3DE-FACBADD20ADB}.Bootstrap|x86.ActiveCfg = Release|Any CPU
{54795C40-B3E8-4DBB-A3DE-FACBADD20ADB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{54795C40-B3E8-4DBB-A3DE-FACBADD20ADB}.Debug|Any CPU.Build.0 = Debug|Any CPU
@@ -741,7 +738,6 @@ Global
{FD4B2006-B518-4884-B196-C2EF2B83FD6F}.Bootstrap|Any CPU.ActiveCfg = Release|Any CPU
{FD4B2006-B518-4884-B196-C2EF2B83FD6F}.Bootstrap|Any CPU.Build.0 = Release|Any CPU
{FD4B2006-B518-4884-B196-C2EF2B83FD6F}.Bootstrap|Mixed Platforms.ActiveCfg = Release|Any CPU
- {FD4B2006-B518-4884-B196-C2EF2B83FD6F}.Bootstrap|Mixed Platforms.Build.0 = Release|Any CPU
{FD4B2006-B518-4884-B196-C2EF2B83FD6F}.Bootstrap|x86.ActiveCfg = Release|Any CPU
{FD4B2006-B518-4884-B196-C2EF2B83FD6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD4B2006-B518-4884-B196-C2EF2B83FD6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
@@ -757,7 +753,6 @@ Global
{0D162A82-CBC1-4A39-916D-E1079B212DDE}.Bootstrap|Any CPU.ActiveCfg = Release|Any CPU
{0D162A82-CBC1-4A39-916D-E1079B212DDE}.Bootstrap|Any CPU.Build.0 = Release|Any CPU
{0D162A82-CBC1-4A39-916D-E1079B212DDE}.Bootstrap|Mixed Platforms.ActiveCfg = Release|Any CPU
- {0D162A82-CBC1-4A39-916D-E1079B212DDE}.Bootstrap|Mixed Platforms.Build.0 = Release|Any CPU
{0D162A82-CBC1-4A39-916D-E1079B212DDE}.Bootstrap|x86.ActiveCfg = Release|Any CPU
{0D162A82-CBC1-4A39-916D-E1079B212DDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0D162A82-CBC1-4A39-916D-E1079B212DDE}.Debug|Any CPU.Build.0 = Debug|Any CPU
@@ -1166,7 +1161,6 @@ Global
{6882C74B-3ED2-4D76-9E7B-67B6A28808BC}.Bootstrap|Any CPU.ActiveCfg = Release|Any CPU
{6882C74B-3ED2-4D76-9E7B-67B6A28808BC}.Bootstrap|Any CPU.Build.0 = Release|Any CPU
{6882C74B-3ED2-4D76-9E7B-67B6A28808BC}.Bootstrap|Mixed Platforms.ActiveCfg = Release|Any CPU
- {6882C74B-3ED2-4D76-9E7B-67B6A28808BC}.Bootstrap|Mixed Platforms.Build.0 = Release|Any CPU
{6882C74B-3ED2-4D76-9E7B-67B6A28808BC}.Bootstrap|x86.ActiveCfg = Release|Any CPU
{6882C74B-3ED2-4D76-9E7B-67B6A28808BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6882C74B-3ED2-4D76-9E7B-67B6A28808BC}.Debug|Any CPU.Build.0 = Debug|Any CPU
@@ -1180,7 +1174,6 @@ Global
{6882C74B-3ED2-4D76-9E7B-67B6A28808BC}.Release|x86.ActiveCfg = Release|Any CPU
{23476FAD-3712-4A4B-90C0-CCCC9AC8D953}.Bootstrap|Any CPU.ActiveCfg = Release|x86
{23476FAD-3712-4A4B-90C0-CCCC9AC8D953}.Bootstrap|Mixed Platforms.ActiveCfg = Release|x86
- {23476FAD-3712-4A4B-90C0-CCCC9AC8D953}.Bootstrap|Mixed Platforms.Build.0 = Release|x86
{23476FAD-3712-4A4B-90C0-CCCC9AC8D953}.Bootstrap|x86.ActiveCfg = Release|x86
{23476FAD-3712-4A4B-90C0-CCCC9AC8D953}.Debug|Any CPU.ActiveCfg = Debug|x86
{23476FAD-3712-4A4B-90C0-CCCC9AC8D953}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
@@ -1194,7 +1187,6 @@ Global
{23476FAD-3712-4A4B-90C0-CCCC9AC8D953}.Release|x86.Build.0 = Release|x86
{3296FE8A-A2BA-4291-8FA0-184CA14E1271}.Bootstrap|Any CPU.ActiveCfg = Release|x86
{3296FE8A-A2BA-4291-8FA0-184CA14E1271}.Bootstrap|Mixed Platforms.ActiveCfg = Release|x86
- {3296FE8A-A2BA-4291-8FA0-184CA14E1271}.Bootstrap|Mixed Platforms.Build.0 = Release|x86
{3296FE8A-A2BA-4291-8FA0-184CA14E1271}.Bootstrap|x86.ActiveCfg = Release|x86
{3296FE8A-A2BA-4291-8FA0-184CA14E1271}.Debug|Any CPU.ActiveCfg = Debug|x86
{3296FE8A-A2BA-4291-8FA0-184CA14E1271}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
diff --git a/source2/Build/Cosmos.Build.MSBuild/Cosmos.Build.MSBuild.csproj b/source2/Build/Cosmos.Build.MSBuild/Cosmos.Build.MSBuild.csproj
index bf0a4082e..6faf9db7b 100644
--- a/source2/Build/Cosmos.Build.MSBuild/Cosmos.Build.MSBuild.csproj
+++ b/source2/Build/Cosmos.Build.MSBuild/Cosmos.Build.MSBuild.csproj
@@ -79,7 +79,7 @@
-
+
diff --git a/source2/Build/Cosmos.Build.MSBuild/Cosmos.targets b/source2/Build/Cosmos.Build.MSBuild/Cosmos.targets
index 83c7bb322..3c739d1a9 100644
--- a/source2/Build/Cosmos.Build.MSBuild/Cosmos.targets
+++ b/source2/Build/Cosmos.Build.MSBuild/Cosmos.targets
@@ -50,7 +50,7 @@
Condition="$(IsELF) == 'true'"/>
@@ -69,7 +69,7 @@
diff --git a/source2/Build/Cosmos.Build.MSBuild/ExtractMapFromElfFile.cs b/source2/Build/Cosmos.Build.MSBuild/ExtractMapFromElfFile.cs
index d06cca195..69828674c 100644
--- a/source2/Build/Cosmos.Build.MSBuild/ExtractMapFromElfFile.cs
+++ b/source2/Build/Cosmos.Build.MSBuild/ExtractMapFromElfFile.cs
@@ -21,7 +21,7 @@ namespace Cosmos.Build.MSBuild
}
[Required]
- public string OutputFile
+ public string DebugInfoFile
{
get;
set;
@@ -98,7 +98,10 @@ namespace Cosmos.Build.MSBuild
xResult.Add(xAddress, xLabel);
}
#endregion
- SourceInfo.WriteToFile(xResult, Path.Combine(WorkingDir, OutputFile));
+ using (var xDebugInfo = new DebugInfo(DebugInfoFile))
+ {
+ xDebugInfo.WriteAddressLabelMappings(xResult);
+ }
return true;
}
diff --git a/source2/Build/Cosmos.Build.MSBuild/IL2CPUTask.cs b/source2/Build/Cosmos.Build.MSBuild/IL2CPUTask.cs
index 7b2227a7f..18ca7f228 100644
--- a/source2/Build/Cosmos.Build.MSBuild/IL2CPUTask.cs
+++ b/source2/Build/Cosmos.Build.MSBuild/IL2CPUTask.cs
@@ -13,6 +13,7 @@ using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
+using Cosmos.Debug.Common;
namespace Cosmos.Build.MSBuild {
// Class is separated from MSBuild task so we can call it from debugging and standalone applications.
@@ -219,36 +220,40 @@ namespace Cosmos.Build.MSBuild {
DebugCom = 0;
}
var xAsm = new AppAssemblerNasm(DebugCom);
- xAsm.DebugMode = mDebugMode;
- xAsm.TraceAssemblies = mTraceAssemblies;
+ File.Delete(xOutputFilename + ".cpdb");
+ using (var xDebugInfo = new DebugInfo(xOutputFilename + ".cpdb"))
+ {
+ xAsm.DebugInfo = xDebugInfo;
+ xAsm.DebugMode = mDebugMode;
+ xAsm.TraceAssemblies = mTraceAssemblies;
#if OUTPUT_ELF
xAsm.EmitELF = true;
#endif
- var xNasmAsm = (AssemblerNasm)xAsm.Assembler;
- xAsm.Assembler.Initialize();
- using (var xScanner = new ILScanner(xAsm))
- {
- xScanner.TempDebug += x => LogMessage(x);
- if (EnableLogging)
+ var xNasmAsm = (AssemblerNasm)xAsm.Assembler;
+ xAsm.Assembler.Initialize();
+ using (var xScanner = new ILScanner(xAsm))
{
- xScanner.EnableLogging(xOutputFilename + ".log.html");
- }
- // TODO: shouldn't be here?
- xScanner.QueueMethod(xInitMethod.DeclaringType.BaseType.GetMethod("Start"));
- xScanner.Execute(xInitMethod);
-
- using (var xOut = new StreamWriter(OutputFilename, false))
- {
- if (EmitDebugSymbols)
+ xScanner.TempDebug += x => LogMessage(x);
+ if (EnableLogging)
{
- xNasmAsm.FlushText(xOut);
- File.Delete(xOutputFilename + ".cpdb");
- xAsm.WriteDebugSymbols(xOutputFilename + ".cpdb");
+ xScanner.EnableLogging(xOutputFilename + ".log.html");
}
- else
+ // TODO: shouldn't be here?
+ xScanner.QueueMethod(xInitMethod.DeclaringType.BaseType.GetMethod("Start"));
+ xScanner.Execute(xInitMethod);
+
+ using (var xOut = new StreamWriter(OutputFilename, false))
{
- xAsm.Assembler.FlushText(xOut);
+ if (EmitDebugSymbols)
+ {
+ xNasmAsm.FlushText(xOut);
+ xAsm.FinalizeDebugInfo();
+ }
+ else
+ {
+ xAsm.Assembler.FlushText(xOut);
+ }
}
}
}
diff --git a/source2/Build/Cosmos.Build.MSBuild/ReadNAsmMapToCosmosMap.cs b/source2/Build/Cosmos.Build.MSBuild/ReadNAsmMapToDebugInfo.cs
similarity index 70%
rename from source2/Build/Cosmos.Build.MSBuild/ReadNAsmMapToCosmosMap.cs
rename to source2/Build/Cosmos.Build.MSBuild/ReadNAsmMapToDebugInfo.cs
index 977496403..138378f45 100644
--- a/source2/Build/Cosmos.Build.MSBuild/ReadNAsmMapToCosmosMap.cs
+++ b/source2/Build/Cosmos.Build.MSBuild/ReadNAsmMapToDebugInfo.cs
@@ -8,7 +8,7 @@ using Cosmos.Debug.Common;
namespace Cosmos.Build.MSBuild
{
- public class ReadNAsmMapToCosmosMap : AppDomainIsolatedTask
+ public class ReadNAsmMapToDebugInfo : AppDomainIsolatedTask
{
[Required]
public string InputBaseDir
@@ -18,7 +18,7 @@ namespace Cosmos.Build.MSBuild
}
[Required]
- public string OutputFile
+ public string DebugInfoFile
{
get;
set;
@@ -32,7 +32,10 @@ namespace Cosmos.Build.MSBuild
Log.LogError("No SourceInfos found!");
return false;
}
- SourceInfo.WriteToFile(xSourceInfos, OutputFile);
+ using (var xDebugInfo = new DebugInfo(DebugInfoFile))
+ {
+ xDebugInfo.WriteAddressLabelMappings(xSourceInfos);
+ }
return true;
}
diff --git a/source2/Debug/Cosmos.Debug.Common/Cosmos.Debug.Common.csproj b/source2/Debug/Cosmos.Debug.Common/Cosmos.Debug.Common.csproj
index 800a5f22e..642e8f9db 100644
--- a/source2/Debug/Cosmos.Debug.Common/Cosmos.Debug.Common.csproj
+++ b/source2/Debug/Cosmos.Debug.Common/Cosmos.Debug.Common.csproj
@@ -88,6 +88,7 @@
+
diff --git a/source2/Debug/Cosmos.Debug.Common/DebugInfo.cs b/source2/Debug/Cosmos.Debug.Common/DebugInfo.cs
new file mode 100644
index 000000000..4f7c15d7c
--- /dev/null
+++ b/source2/Debug/Cosmos.Debug.Common/DebugInfo.cs
@@ -0,0 +1,263 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using FirebirdSql.Data.FirebirdClient;
+using System.IO;
+using Microsoft.Win32;
+using FirebirdSql.Data.Isql;
+
+namespace Cosmos.Debug.Common
+{
+ public class DebugInfo: IDisposable
+ {
+ public class MLDebugSymbol
+ {
+ public string LabelName
+ {
+ get;
+ set;
+ }
+
+ public uint Address
+ {
+ get;
+ set;
+ }
+
+ public int StackDifference
+ {
+ get;
+ set;
+ }
+
+ public string AssemblyFile
+ {
+ get;
+ set;
+ }
+ public int TypeToken
+ {
+ get;
+ set;
+ }
+ public int MethodToken
+ {
+ get;
+ set;
+ }
+ public int ILOffset
+ {
+ get;
+ set;
+ }
+
+ public string MethodName
+ {
+ get;
+ set;
+ }
+ }
+ private FbConnection mConnection;
+
+ public DebugInfo(string file)
+ {
+ var xCreate = !File.Exists(file);
+ if (xCreate)
+ {
+ mConnection = CreateCPDB(file);
+ }
+ else
+ {
+ mConnection = OpenCPDB(file, false);
+ }
+ }
+ #region connection utilities
+ private static FbConnection OpenCPDB(string aPathname, bool aCreate)
+ {
+ var xCSB = new FbConnectionStringBuilder();
+ xCSB.ServerType = FbServerType.Embedded;
+ xCSB.Database = aPathname;
+ xCSB.UserID = "sysdba";
+ xCSB.Password = "masterkey";
+ xCSB.Pooling = false;
+
+ // Ugh - The curr dir is the actual .cosmos dir. But we dont want to
+ // copy the FB Embedded DLLs everywhere, and we don't want them in system
+ // or path as they might conflict with other apps.
+ // However the FB .NET provider doesnt let us set the path, so we hack it
+ // by changing the current dir right before the first load (create or open).
+ // We set it back after.
+ string xCurrDir = Directory.GetCurrentDirectory();
+ using (var xKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Cosmos", false))
+ {
+ string xCosmosDir = (string)xKey.GetValue("");
+ Directory.SetCurrentDirectory(Path.Combine(xCosmosDir, @"Build\VSIP"));
+ }
+
+ if (aCreate)
+ {
+ File.Delete(aPathname);
+ FbConnection.CreateDatabase(xCSB.ToString(), 16384, false, true); // Specifying false to forcedwrites will improve database speed.
+ }
+
+ FbConnection DBConn = new FbConnection(xCSB.ToString());
+ DBConn.Open();
+
+ // Set the current directory back to the original
+ Directory.SetCurrentDirectory(xCurrDir);
+
+ return DBConn;
+ }
+
+ private static FbConnection CreateCPDB(string aPathname)
+ {
+ FbConnection DBConn = OpenCPDB(aPathname, true);
+ var xExec = new FbBatchExecution(DBConn);
+
+ xExec.SqlStatements.Add(
+ "CREATE TABLE MLSYMBOL ("
+ + " LABELNAME VARCHAR(255) NOT NULL"
+ + " , ADDRESS BIGINT NOT NULL"
+ + " , STACKDIFF INT NOT NULL"
+ + " , ILASMFILE VARCHAR(255) NOT NULL"
+ + " , TYPETOKEN INT NOT NULL"
+ + " , METHODTOKEN INT NOT NULL"
+ + " , ILOFFSET INT NOT NULL"
+ + " , METHODNAME VARCHAR(255) NOT NULL"
+ + ");"
+ );
+
+ xExec.SqlStatements.Add(
+ "CREATE TABLE ADDRESSLABELMAPPING ("
+ + " LABELNAME VARCHAR(255) NOT NULL"
+ + ", ADDRESS BIGINT NOT NULL"
+ + ");");
+
+ xExec.Execute();
+ // Batch execution closes the connection, so we have to reopen it
+ DBConn.Open();
+
+ return DBConn;
+ }
+ #endregion
+
+ #region MLDebugSymbol code
+ public void WriteSymbolsListToFile(IEnumerable aSymbols)
+ {
+ using (FbTransaction transaction = mConnection.BeginTransaction())
+ {
+ using (var xCmd = mConnection.CreateCommand())
+ {
+ xCmd.Transaction = transaction;
+ xCmd.CommandText = "INSERT INTO MLSYMBOL (LABELNAME, ADDRESS, STACKDIFF, ILASMFILE, TYPETOKEN, METHODTOKEN, ILOFFSET, METHODNAME)" +
+ " VALUES (@LABELNAME, @ADDRESS, @STACKDIFF, @ILASMFILE, @TYPETOKEN, @METHODTOKEN, @ILOFFSET, @METHODNAME)";
+
+ xCmd.Parameters.Add("@LABELNAME", FbDbType.VarChar);
+ xCmd.Parameters.Add("@ADDRESS", FbDbType.BigInt);
+ xCmd.Parameters.Add("@STACKDIFF", FbDbType.Integer);
+ xCmd.Parameters.Add("@ILASMFILE", FbDbType.VarChar);
+ xCmd.Parameters.Add("@TYPETOKEN", FbDbType.Integer);
+ xCmd.Parameters.Add("@METHODTOKEN", FbDbType.Integer);
+ xCmd.Parameters.Add("@ILOFFSET", FbDbType.Integer);
+ xCmd.Parameters.Add("@METHODNAME", FbDbType.VarChar);
+ xCmd.Prepare();
+
+ // Is a real DB now, but we still store all in RAM. We dont need to. Need to change to query DB as needed instead.
+ foreach (var xItem in aSymbols)
+ {
+ xCmd.Parameters[0].Value = xItem.LabelName;
+ xCmd.Parameters[1].Value = xItem.Address;
+ xCmd.Parameters[2].Value = xItem.StackDifference;
+ xCmd.Parameters[3].Value = xItem.AssemblyFile;
+ xCmd.Parameters[4].Value = xItem.TypeToken;
+ xCmd.Parameters[5].Value = xItem.MethodToken;
+ xCmd.Parameters[6].Value = xItem.ILOffset;
+ xCmd.Parameters[7].Value = xItem.MethodName;
+ xCmd.ExecuteNonQuery();
+ }
+ }
+
+ transaction.Commit();
+ }
+ }
+ public void ReadSymbolsList(List aSymbols)
+ {
+ using (var xCmd = mConnection.CreateCommand())
+ {
+ xCmd.CommandText = "select LABELNAME, ADDRESS, STACKDIFF, ILASMFILE, TYPETOKEN, METHODTOKEN, ILOFFSET, METHODNAME from MLSYMBOL";
+ using (var xReader = xCmd.ExecuteReader())
+ {
+ while (xReader.Read())
+ {
+ aSymbols.Add(new MLDebugSymbol
+ {
+ LabelName = xReader.GetString(0),
+ Address = (uint)xReader.GetInt64(1),
+ StackDifference = xReader.GetInt32(2),
+ AssemblyFile = xReader.GetString(3),
+ TypeToken = xReader.GetInt32(4),
+ MethodToken = xReader.GetInt32(5),
+ ILOffset = xReader.GetInt32(6),
+ MethodName = xReader.GetString(7)
+ });
+ }
+ }
+ }
+ }
+
+ #endregion
+
+ #region address-label mappings
+ public void ReadAddressLabelMappings(out IDictionary oAddressLabelMappings, out IDictionary oLabelAddressMappings)
+ {
+ oAddressLabelMappings = new Dictionary();
+ oLabelAddressMappings = new Dictionary();
+ using (var xCmd = mConnection.CreateCommand())
+ {
+ xCmd.CommandText = "select LABELNAME, ADDRESS from ADDRESSLABELMAPPING";
+ using (var xReader = xCmd.ExecuteReader())
+ {
+ while (xReader.Read())
+ {
+ oAddressLabelMappings.Add((uint)xReader.GetInt64(1), xReader.GetString(0));
+ oLabelAddressMappings.Add(xReader.GetString(0), (uint)xReader.GetInt64(1));
+ }
+ }
+ }
+ }
+
+ public void WriteAddressLabelMappings(SortedList aMap)
+ {
+ using (var xTrans = mConnection.BeginTransaction())
+ {
+ using (var xCmd = mConnection.CreateCommand())
+ {
+ xCmd.Transaction = xTrans;
+ xCmd.CommandText = "insert into ADDRESSLABELMAPPING (LABELNAME, ADDRESS) values (@LABELNAME, @ADDRESS)";
+ xCmd.Parameters.Add("@LABELNAME", FbDbType.VarChar);
+ xCmd.Parameters.Add("@ADDRESS", FbDbType.BigInt);
+ xCmd.Prepare();
+ foreach (var xItem in aMap)
+ {
+ xCmd.Parameters[0].Value = xItem.Value;
+ xCmd.Parameters[1].Value = xItem.Key;
+ xCmd.ExecuteNonQuery();
+ }
+ xTrans.Commit();
+ }
+ }
+ }
+ #endregion
+
+ public void Dispose()
+ {
+ if (mConnection != null)
+ {
+ var xCon = mConnection;
+ mConnection = null;
+ xCon.Dispose();
+ }
+ GC.SuppressFinalize(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/source2/Debug/Cosmos.Debug.Common/DebugSymbol.cs b/source2/Debug/Cosmos.Debug.Common/DebugSymbol.cs
index 5be6049ad..535e8c6d1 100644
--- a/source2/Debug/Cosmos.Debug.Common/DebugSymbol.cs
+++ b/source2/Debug/Cosmos.Debug.Common/DebugSymbol.cs
@@ -40,7 +40,7 @@ namespace Cosmos.Debug.Common
}
}
- public class MLDebugSymbol
+ public class MLDebugSymbol_Old
{
public static FbConnection OpenOrCreateCPDB(string aPathName)
{
@@ -122,76 +122,6 @@ namespace Cosmos.Debug.Common
return DBConn;
}
- public static void WriteSymbolsListToFile(IEnumerable aSymbols, string aFile)
- {
- using (FbConnection DBConn = OpenOrCreateCPDB(aFile))
- {
- using (FbTransaction transaction = DBConn.BeginTransaction())
- {
- using (var xCmd = DBConn.CreateCommand())
- {
- xCmd.Transaction = transaction;
- xCmd.CommandText = "INSERT INTO MLSYMBOL (LABELNAME, ADDRESS, STACKDIFF, ILASMFILE, TYPETOKEN, METHODTOKEN, ILOFFSET, METHODNAME)" +
- " VALUES (@LABELNAME, @ADDRESS, @STACKDIFF, @ILASMFILE, @TYPETOKEN, @METHODTOKEN, @ILOFFSET, @METHODNAME)";
-
- xCmd.Parameters.Add("@LABELNAME", FbDbType.VarChar);
- xCmd.Parameters.Add("@ADDRESS", FbDbType.BigInt);
- xCmd.Parameters.Add("@STACKDIFF", FbDbType.Integer);
- xCmd.Parameters.Add("@ILASMFILE", FbDbType.VarChar);
- xCmd.Parameters.Add("@TYPETOKEN", FbDbType.Integer);
- xCmd.Parameters.Add("@METHODTOKEN", FbDbType.Integer);
- xCmd.Parameters.Add("@ILOFFSET", FbDbType.Integer);
- xCmd.Parameters.Add("@METHODNAME", FbDbType.VarChar);
- xCmd.Prepare();
-
- // Is a real DB now, but we still store all in RAM. We dont need to. Need to change to query DB as needed instead.
- foreach (var xItem in aSymbols)
- {
- xCmd.Parameters[0].Value = xItem.LabelName;
- xCmd.Parameters[1].Value = xItem.Address;
- xCmd.Parameters[2].Value = xItem.StackDifference;
- xCmd.Parameters[3].Value = xItem.AssemblyFile;
- xCmd.Parameters[4].Value = xItem.TypeToken;
- xCmd.Parameters[5].Value = xItem.MethodToken;
- xCmd.Parameters[6].Value = xItem.ILOffset;
- xCmd.Parameters[7].Value = xItem.MethodName;
- xCmd.ExecuteNonQuery();
- }
- }
-
- transaction.Commit();
- }
- }
- }
-
- public static void ReadSymbolsListFromFile(List aSymbols, string aFile)
- {
- using (var xConn = OpenCPDB(aFile, false))
- {
- using (var xCmd = xConn.CreateCommand())
- {
- xCmd.CommandText = "select LABELNAME, ADDRESS, STACKDIFF, ILASMFILE, TYPETOKEN, METHODTOKEN, ILOFFSET, METHODNAME from MLSYMBOL";
- using (var xReader = xCmd.ExecuteReader())
- {
- while (xReader.Read())
- {
- aSymbols.Add(new MLDebugSymbol
- {
- LabelName=xReader.GetString(0),
- Address = (uint)xReader.GetInt64(1),
- StackDifference = xReader.GetInt32(2),
- AssemblyFile = xReader.GetString(3),
- TypeToken = xReader.GetInt32(4),
- MethodToken = xReader.GetInt32(5),
- ILOffset = xReader.GetInt32(6),
- MethodName = xReader.GetString(7)
- });
- }
- }
- }
- }
- }
-
public string LabelName
{
get;
diff --git a/source2/Debug/Cosmos.Debug.Common/SourceInfo.cs b/source2/Debug/Cosmos.Debug.Common/SourceInfo.cs
index b88fe4e9d..fa599da45 100644
--- a/source2/Debug/Cosmos.Debug.Common/SourceInfo.cs
+++ b/source2/Debug/Cosmos.Debug.Common/SourceInfo.cs
@@ -50,51 +50,6 @@ namespace Cosmos.Debug.Common
set;
}
- public static void WriteToFile(SortedList aMap, string outFile)
- {
- using (var xConn = MLDebugSymbol.OpenOrCreateCPDB(outFile))
- {
- using (var xTrans = xConn.BeginTransaction())
- {
- using (var xCmd = xConn.CreateCommand())
- {
- xCmd.Transaction = xTrans;
- xCmd.CommandText = "insert into ADDRESSLABELMAPPING (LABELNAME, ADDRESS) values (@LABELNAME, @ADDRESS)";
- xCmd.Parameters.Add("@LABELNAME", FbDbType.VarChar);
- xCmd.Parameters.Add("@ADDRESS", FbDbType.BigInt);
- xCmd.Prepare();
- foreach(var xItem in aMap){
- xCmd.Parameters[0].Value = xItem.Value;
- xCmd.Parameters[1].Value = xItem.Key;
- xCmd.ExecuteNonQuery();
- }
- xTrans.Commit();
- }
- }
- }
- }
-
- public static void ReadFromFile(string aFile, out IDictionary oAddressLabelMappings, out IDictionary oLabelAddressMappings)
- {
- oAddressLabelMappings = new Dictionary();
- oLabelAddressMappings = new Dictionary();
- using (var xConn = MLDebugSymbol.OpenOrCreateCPDB(aFile))
- {
- using (var xCmd = xConn.CreateCommand())
- {
- xCmd.CommandText = "select LABELNAME, ADDRESS from ADDRESSLABELMAPPING";
- using (var xReader = xCmd.ExecuteReader())
- {
- while (xReader.Read())
- {
- oAddressLabelMappings.Add((uint)xReader.GetInt64(1), xReader.GetString(0));
- oLabelAddressMappings.Add(xReader.GetString(0), (uint)xReader.GetInt64(1));
- }
- }
- }
- }
- }
-
public static SortedList ParseMapFile(String buildPath)
{
var xSourceStrings = File.ReadAllLines(Path.Combine(buildPath, "main.map"));
@@ -142,11 +97,12 @@ namespace Cosmos.Debug.Common
return xIdx;
}
- public static SourceInfos GetSourceInfo(IDictionary aAddressLabelMappings, IDictionary aLabelAddressMappings, string aDebugFile) {
- var xSymbolsList = new List();
- MLDebugSymbol.ReadSymbolsListFromFile(xSymbolsList, aDebugFile);
+ public static SourceInfos GetSourceInfo(IDictionary aAddressLabelMappings, IDictionary aLabelAddressMappings, DebugInfo debugInfo) {
+ var xSymbolsList = new List();
+ debugInfo.ReadSymbolsList(xSymbolsList);
#region sort
- xSymbolsList.Sort(delegate(MLDebugSymbol a, MLDebugSymbol b) {
+ xSymbolsList.Sort(delegate(DebugInfo.MLDebugSymbol a, DebugInfo.MLDebugSymbol b)
+ {
if (a == null) {
throw new ArgumentNullException("a");
}
diff --git a/source2/Debug/Cosmos.Debug.VSDebugEngine/AD7.Impl/AD7Process.cs b/source2/Debug/Cosmos.Debug.VSDebugEngine/AD7.Impl/AD7Process.cs
index aa5cad0d5..fb51d9cb0 100644
--- a/source2/Debug/Cosmos.Debug.VSDebugEngine/AD7.Impl/AD7Process.cs
+++ b/source2/Debug/Cosmos.Debug.VSDebugEngine/AD7.Impl/AD7Process.cs
@@ -189,24 +189,29 @@ namespace Cosmos.Debug.VSDebugEngine {
IDictionary xAddressLabelMappings;
IDictionary xLabelAddressMappings;
- string xCpdbPath = Path.ChangeExtension(mISO, "cpdb");
+
+ string xCpdbPath = Path.ChangeExtension(mISO, "cpdb");
if (!File.Exists(xCpdbPath))
{
throw new Exception("Debug data file " + xCpdbPath + " not found! Could be a omitted build process of Cosmos project so that not created.");
}
- Cosmos.Debug.Common.SourceInfo.ReadFromFile(xCpdbPath, out xAddressLabelMappings, out xLabelAddressMappings);
- if (xAddressLabelMappings.Count == 0)
+
+ using (var xDebugInfo = new DebugInfo(xCpdbPath))
{
- throw new Exception("Debug data not found: LabelByAddressMapping");
- }
+ xDebugInfo.ReadAddressLabelMappings(out xAddressLabelMappings, out xLabelAddressMappings);
+ if (xAddressLabelMappings.Count == 0)
+ {
+ throw new Exception("Debug data not found: LabelByAddressMapping");
+ }
- mSourceMappings = Cosmos.Debug.Common.SourceInfo.GetSourceInfo(xAddressLabelMappings, xLabelAddressMappings, xCpdbPath);
+ mSourceMappings = Cosmos.Debug.Common.SourceInfo.GetSourceInfo(xAddressLabelMappings, xLabelAddressMappings, xDebugInfo);
- if (mSourceMappings.Count == 0) {
- throw new Exception("Debug data not found: SourceMappings");
+ if (mSourceMappings.Count == 0)
+ {
+ throw new Exception("Debug data not found: SourceMappings");
+ }
+ mReverseSourceMappings = new ReverseSourceInfos(mSourceMappings);
}
- mReverseSourceMappings = new ReverseSourceInfos(mSourceMappings);
-
if (StringComparer.InvariantCultureIgnoreCase.Equals(mDebugInfo["BuildTarget"], "vmware")) {
mDbgConnector = new Cosmos.Debug.Common.DebugConnectorPipeServer();
} else {
diff --git a/source2/IL2CPU/Cosmos.IL2CPU.X86/AppAssemblerNasm.cs b/source2/IL2CPU/Cosmos.IL2CPU.X86/AppAssemblerNasm.cs
index bf0536616..b41ce0669 100644
--- a/source2/IL2CPU/Cosmos.IL2CPU.X86/AppAssemblerNasm.cs
+++ b/source2/IL2CPU/Cosmos.IL2CPU.X86/AppAssemblerNasm.cs
@@ -13,7 +13,7 @@ using CPUx86 = Cosmos.Compiler.Assembler.X86;
namespace Cosmos.IL2CPU.X86
{
- public class AppAssemblerNasm: AppAssembler
+ public class AppAssemblerNasm : AppAssembler
{
public AppAssemblerNasm(byte comNumber)
: base(comNumber)
@@ -25,423 +25,456 @@ namespace Cosmos.IL2CPU.X86
}
- protected override void MethodBegin(MethodInfo aMethod) {
- base.MethodBegin(aMethod);
- if (aMethod.PluggedMethod != null)
- {
- new Label("PLUG_FOR___" + MethodInfoLabelGenerator.GenerateLabelName(aMethod.PluggedMethod.MethodBase));
- }
- else
- {
- new Label(aMethod.MethodBase);
- }
- if (aMethod.MethodBase.IsStatic && aMethod.MethodBase is ConstructorInfo)
- {
- new Comment("This is a static constructor. see if it has been called already, and if so, return.");
- var xName = DataMember.FilterStringForIncorrectChars("CCTOR_CALLED__" + MethodInfoLabelGenerator.GetFullName(aMethod.MethodBase.DeclaringType));
- var xAsmMember = new DataMember(xName, (byte)0);
- Assembler.DataMembers.Add(xAsmMember);
- new Compare { DestinationRef = ElementReference.New(xName), DestinationIsIndirect = true, Size = 8, SourceValue = 1 };
- new ConditionalJump { Condition = ConditionalTestEnum.Equal, DestinationLabel = ".BeforeQuickReturn" };
- new Move { DestinationRef = ElementReference.New(xName), DestinationIsIndirect = true, Size = 8, SourceValue = 1 };
- new Jump { DestinationLabel = ".AfterCCTorAlreadyCalledCheck"};
- new Label(".BeforeQuickReturn");
- new Move { DestinationReg = RegistersEnum.ECX, SourceValue = 0 };
- new Return { };
- new Label(".AfterCCTorAlreadyCalledCheck");
- }
-
- new Push { DestinationReg = Registers.EBP };
- new Move { DestinationReg = Registers.EBP, SourceReg = Registers.ESP };
- //new CPUx86.Push("0");
- //if (!(aLabelName.Contains("Cosmos.Kernel.Serial") || aLabelName.Contains("Cosmos.Kernel.Heap"))) {
- // new CPUx86.Push(LdStr.GetContentsArrayName(aAssembler, aLabelName));
- // MethodBase xTempMethod = Engine.GetMethodBase(Engine.GetType("Cosmos.Kernel", "Cosmos.Kernel.Serial"), "Write", "System.Byte", "System.String");
- // new CPUx86.Call(MethodInfoLabelGenerator.GenerateLabelName(xTempMethod));
- // Engine.QueueMethod(xTempMethod);
- //}
- if (aMethod.MethodAssembler == null && aMethod.PlugMethod == null) {
- var xBody = aMethod.MethodBase.GetMethodBody();
- if (xBody != null) {
- foreach (var xLocal in xBody.LocalVariables) {
- new Comment("Local " + xLocal.LocalIndex);
- new Sub { DestinationReg = Registers.ESP, SourceValue = ILOp.Align(ILOp.SizeOfType(xLocal.LocalType), 4) };
- }
- }
- }
- //foreach (var xLocal in aLocals) {
- // aAssembler.StackContents.Push(new StackContent(xLocal.Size, xLocal.VariableType));
- // for (int i = 0; i < (xLocal.Size / 4); i++) {
- // new CPUx86.Push { DestinationValue = 0 };
- // }
- //}
- //if (aDebugMode && aIsNonDebuggable) {
- // new CPUx86.Call { DestinationLabel = "DebugPoint_DebugSuspend" };
- //}
- #region Load CodeOffset
- if (DebugMode == DebugMode.Source)
- {
- var xSymbolReader = GetSymbolReaderForAssembly(aMethod.MethodBase.DeclaringType.Assembly);
- if (xSymbolReader != null)
- {
- var xSmbMethod = xSymbolReader.GetMethod(new SymbolToken(aMethod.MethodBase.MetadataToken));
- // This gets the Sequence Points.
- // Sequence Points are spots that identify what the compiler/debugger says is a spot
- // that a breakpoint can occur one. Essentially, an atomic source line in C#
- if (xSmbMethod != null)
- {
- xCodeOffsets = new int[xSmbMethod.SequencePointCount];
- var xCodeDocuments = new ISymbolDocument[xSmbMethod.SequencePointCount];
- xCodeLineNumbers = new int[xSmbMethod.SequencePointCount];
- var xCodeColumns = new int[xSmbMethod.SequencePointCount];
- var xCodeEndLines = new int[xSmbMethod.SequencePointCount];
- var xCodeEndColumns = new int[xSmbMethod.SequencePointCount];
- xSmbMethod.GetSequencePoints(xCodeOffsets, xCodeDocuments
- , xCodeLineNumbers, xCodeColumns, xCodeEndLines, xCodeEndColumns);
- }
- }
- }
- #endregion
- }
-
- protected override void MethodEnd(MethodInfo aMethod) {
- base.MethodEnd(aMethod);
- uint xReturnSize = 0;
- var xMethInfo = aMethod.MethodBase as System.Reflection.MethodInfo;
- if (xMethInfo != null) {
- xReturnSize = ILOp.Align(ILOp.SizeOfType(xMethInfo.ReturnType), 4);
- }
- new Label(ILOp.GetMethodLabel(aMethod) + EndOfMethodLabelNameNormal);
- new CPUx86.Move { DestinationReg = CPUx86.Registers.ECX, SourceValue = 0 };
- var xTotalArgsSize = (from item in aMethod.MethodBase.GetParameters()
- select (int)ILOp.Align(ILOp.SizeOfType(item.ParameterType), 4)).Sum();
- if (!aMethod.MethodBase.IsStatic) {
- if (aMethod.MethodBase.DeclaringType.IsValueType)
- {
- xTotalArgsSize += 4; // only a reference is passed
- }
- else
- {
- xTotalArgsSize += (int)ILOp.Align(ILOp.SizeOfType(aMethod.MethodBase.DeclaringType), 4);
- }
- }
-
- if (aMethod.PluggedMethod != null) {
- xReturnSize = 0;
- xMethInfo = aMethod.PluggedMethod.MethodBase as System.Reflection.MethodInfo;
- if (xMethInfo != null) {
- xReturnSize = ILOp.Align(ILOp.SizeOfType(xMethInfo.ReturnType), 4);
- }
- xTotalArgsSize = (from item in aMethod.PluggedMethod.MethodBase.GetParameters()
- select (int)ILOp.Align(ILOp.SizeOfType(item.ParameterType), 4)).Sum();
- if (!aMethod.PluggedMethod.MethodBase.IsStatic) {
- if (aMethod.PluggedMethod.MethodBase.DeclaringType.IsValueType)
+ protected override void MethodBegin(MethodInfo aMethod)
+ {
+ base.MethodBegin(aMethod);
+ if (aMethod.PluggedMethod != null)
{
- xTotalArgsSize += 4; // only a reference is passed
+ new Label("PLUG_FOR___" + MethodInfoLabelGenerator.GenerateLabelName(aMethod.PluggedMethod.MethodBase));
}
else
{
- xTotalArgsSize += (int)ILOp.Align(ILOp.SizeOfType(aMethod.PluggedMethod.MethodBase.DeclaringType), 4);
+ new Label(aMethod.MethodBase);
+ }
+ if (aMethod.MethodBase.IsStatic && aMethod.MethodBase is ConstructorInfo)
+ {
+ new Comment("This is a static constructor. see if it has been called already, and if so, return.");
+ var xName = DataMember.FilterStringForIncorrectChars("CCTOR_CALLED__" + MethodInfoLabelGenerator.GetFullName(aMethod.MethodBase.DeclaringType));
+ var xAsmMember = new DataMember(xName, (byte)0);
+ Assembler.DataMembers.Add(xAsmMember);
+ new Compare { DestinationRef = ElementReference.New(xName), DestinationIsIndirect = true, Size = 8, SourceValue = 1 };
+ new ConditionalJump { Condition = ConditionalTestEnum.Equal, DestinationLabel = ".BeforeQuickReturn" };
+ new Move { DestinationRef = ElementReference.New(xName), DestinationIsIndirect = true, Size = 8, SourceValue = 1 };
+ new Jump { DestinationLabel = ".AfterCCTorAlreadyCalledCheck" };
+ new Label(".BeforeQuickReturn");
+ new Move { DestinationReg = RegistersEnum.ECX, SourceValue = 0 };
+ new Return { };
+ new Label(".AfterCCTorAlreadyCalledCheck");
}
- }
- }
- if (xReturnSize > 0) {
- //var xArgSize = (from item in aArgs
- // let xSize = item.Size + item.Offset
- // select xSize).FirstOrDefault();
- //new Comment(String.Format("ReturnSize = {0}, ArgumentSize = {1}",
- // aReturnSize,
- // xArgSize));
- //int xOffset = 4;
- //if(xArgSize>0) {
- // xArgSize -= xReturnSize;
- // xOffset = xArgSize;
- //}
- var xOffset = GetResultCodeOffset(xReturnSize, (uint)xTotalArgsSize);
- for (int i = 0; i < xReturnSize / 4; i++) {
- new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX };
- new CPUx86.Move {
- DestinationReg = CPUx86.Registers.EBP,
- DestinationIsIndirect = true,
- DestinationDisplacement = (int)(xOffset + ((i + 0) * 4)),
- SourceReg = Registers.EAX
- };
- // new CPUx86.Move {
- // DestinationReg = CPUx86.Registers.EBP,
- // DestinationIsIndirect = true,
- // DestinationDisplacement = (int)(xOffset + ((i + 1) * 4) + 4 - xReturnSize),
- // SourceReg = Registers.EAX
- // };
- }
- // extra stack space is the space reserved for example when a "public static int TestMethod();" method is called, 4 bytes is pushed, to make room for result;
- }
- new Label(ILOp.GetMethodLabel(aMethod) + EndOfMethodLabelNameException);
- //for (int i = 0; i < aLocAllocItemCount; i++) {
- // new CPUx86.Call { DestinationLabel = aHeapFreeLabel };
- //}
- //if (aDebugMode && aIsNonDebuggable) {
- // new CPUx86.Call { DestinationLabel = "DebugPoint_DebugResume" };
- //}
-
- //if ((from xLocal in aLocals
- // where xLocal.IsReferenceType
- // select 1).Count() > 0 || (from xArg in aArgs
- // where xArg.IsReferenceType
- // select 1).Count() > 0) {
- // new CPUx86.Push { DestinationReg = Registers.ECX };
- // //foreach (MethodInformation.Variable xLocal in aLocals) {
- // // if (xLocal.IsReferenceType) {
- // // Op.Ldloc(aAssembler,
- // // xLocal,
- // // false,
- // // aGetStorageSizeDelegate(xLocal.VariableType));
- // // new CPUx86.Call { DestinationLabel = aDecRefLabel };
- // // }
- // //}
- // //foreach (MethodInformation.Argument xArg in aArgs) {
- // // if (xArg.IsReferenceType) {
- // // Op.Ldarg(aAssembler,
- // // xArg,
- // // false);
- // // //, aGetStorageSizeDelegate(xArg.ArgumentType)
- // // new CPUx86.Call { DestinationLabel = aDecRefLabel };
- // // }
- // //}
- // // todo: add GC code
- // new CPUx86.Pop { DestinationReg = CPUx86.Registers.ECX };
- //}
- if (aMethod.MethodAssembler == null && aMethod.PlugMethod == null) {
- var xBody = aMethod.MethodBase.GetMethodBody();
- if (xBody != null) {
- for (int j = xBody.LocalVariables.Count - 1; j >= 0; j--) {
- int xLocalSize = (int)ILOp.Align(ILOp.SizeOfType(xBody.LocalVariables[j].LocalType), 4);
- new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = (uint)xLocalSize };
- }
- }
- }
- //new CPUx86.Add(CPUx86.Registers_Old.ESP, "0x4");
- //new CPUx86.Compare { DestinationReg = Registers.EBP, SourceReg = Registers.ESP };
- //new CPUx86.ConditionalJump { Condition = ConditionalTestEnum.Equal, DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName(aMethod.MethodBase) + EndOfMethodLabelNameException + "__2" };
- //new CPUx86.Xchg { DestinationReg = Registers.BX, SourceReg = Registers.BX };
- //new CPUx86.Halt();
- // TODO: not nice coding, still a test
- //new CPUx86.Move { DestinationReg = Registers.ESP, SourceReg = Registers.EBP };
- new Label(ILOp.GetMethodLabel(aMethod) + EndOfMethodLabelNameException + "__2");
- new CPUx86.Pop { DestinationReg = CPUx86.Registers.EBP };
- var xRetSize = ((int)xTotalArgsSize) - ((int)xReturnSize);
- if (xRetSize < 0) {
- xRetSize = 0;
- }
- WriteDebug(aMethod.MethodBase, (uint)xRetSize, IL.Call.GetStackSizeToReservate(aMethod.MethodBase));
- new CPUx86.Return { DestinationValue = (uint)xRetSize };
- }
-
- public static uint GetResultCodeOffset(uint aResultSize, uint aTotalArgumentSize)
- {
- uint xOffset = 8;
- if ((aTotalArgumentSize > 0) && (aTotalArgumentSize >= aResultSize))
- {
- xOffset += aTotalArgumentSize;
- xOffset -= aResultSize;
- }
- return xOffset;
- }
-
- private static ISymbolReader GetSymbolReaderForAssembly(Assembly aAssembly)
- {
- try
- {
- return SymbolAccess.GetReaderForFile(aAssembly.Location);
- }
- catch (NotSupportedException)
- {
- return null;
- }
- }
-
- protected override void MethodBegin(string aMethodName) {
- base.MethodBegin(aMethodName);
- new Label(aMethodName);
- new Push { DestinationReg = Registers.EBP };
- new Move { DestinationReg = Registers.EBP, SourceReg = Registers.ESP };
- xCodeOffsets = new int[0];
- }
-
- protected override void MethodEnd(string aMethodName) {
- base.MethodEnd(aMethodName);
- new Label("_END_OF_" + aMethodName);
- new CPUx86.Pop { DestinationReg = CPUx86.Registers.EBP };
- new CPUx86.Return();
- }
-
- private static HashSet mDebugLines = new HashSet();
- private static void WriteDebug(MethodBase aMethod, uint aSize, uint aSize2) {
- var xLine = String.Format("{0}\t{1}\t{2}", MethodInfoLabelGenerator.GenerateFullName(aMethod), aSize, aSize2);
-
- }
- private List mSymbols = new List();
-
- // These are all temp functions until we move to the new assembler.
- // They are used to clean up the old assembler slightly while retaining compatibiltiy for now
- public static string TmpPosLabel(MethodInfo aMethod, int aOffset)
- {
- // todo: fix to be small again.
- return ILOp.GetLabel(aMethod, aOffset);
- //TODO: Change to Hex output, will be smaller and slightly faster for NASM
- //return "POS_" + aMethod.UID + "_" + aOffset;
- }
-
- public static string TmpPosLabel(MethodInfo aMethod, ILOpCode aOpCode)
- {
- return TmpPosLabel(aMethod, aOpCode.Position);
- }
-
- public static string TmpBranchLabel(MethodInfo aMethod, ILOpCode aOpCode)
- {
- return TmpPosLabel(aMethod, ((ILOpCodes.OpBranch)aOpCode).Value);
- }
-
- protected override void BeforeOp(MethodInfo aMethod, ILOpCode aOpCode)
- {
- base.BeforeOp(aMethod, aOpCode);
- new Label(TmpPosLabel(aMethod, aOpCode));
- #region Collection debug information
- if (mSymbols != null)
- {
- var xMLSymbol = new MLDebugSymbol();
- xMLSymbol.LabelName = TmpPosLabel(aMethod, aOpCode);
- xMLSymbol.MethodName = aMethod.MethodBase.GetFullName();
- int xStackSize = (from item in mAssembler.Stack
- let xSize = (item.Size % 4 == 0)
- ? item.Size
- : (item.Size + (4 - (item.Size % 4)))
- select xSize).Sum();
- xMLSymbol.StackDifference = -1;
- if (aMethod.MethodBase != null)
+ new Push { DestinationReg = Registers.EBP };
+ new Move { DestinationReg = Registers.EBP, SourceReg = Registers.ESP };
+ //new CPUx86.Push("0");
+ //if (!(aLabelName.Contains("Cosmos.Kernel.Serial") || aLabelName.Contains("Cosmos.Kernel.Heap"))) {
+ // new CPUx86.Push(LdStr.GetContentsArrayName(aAssembler, aLabelName));
+ // MethodBase xTempMethod = Engine.GetMethodBase(Engine.GetType("Cosmos.Kernel", "Cosmos.Kernel.Serial"), "Write", "System.Byte", "System.String");
+ // new CPUx86.Call(MethodInfoLabelGenerator.GenerateLabelName(xTempMethod));
+ // Engine.QueueMethod(xTempMethod);
+ //}
+ if (aMethod.MethodAssembler == null && aMethod.PlugMethod == null)
{
var xBody = aMethod.MethodBase.GetMethodBody();
if (xBody != null)
{
- var xLocalsSize = (from item in xBody.LocalVariables
- select (int)ILOp.Align(ILOp.SizeOfType(item.LocalType), 4)).Sum();
- xMLSymbol.StackDifference = xLocalsSize + xStackSize;
+ foreach (var xLocal in xBody.LocalVariables)
+ {
+ new Comment("Local " + xLocal.LocalIndex);
+ new Sub { DestinationReg = Registers.ESP, SourceValue = ILOp.Align(ILOp.SizeOfType(xLocal.LocalType), 4) };
+ }
}
}
+ //foreach (var xLocal in aLocals) {
+ // aAssembler.StackContents.Push(new StackContent(xLocal.Size, xLocal.VariableType));
+ // for (int i = 0; i < (xLocal.Size / 4); i++) {
+ // new CPUx86.Push { DestinationValue = 0 };
+ // }
+ //}
+ //if (aDebugMode && aIsNonDebuggable) {
+ // new CPUx86.Call { DestinationLabel = "DebugPoint_DebugSuspend" };
+ //}
+ #region Load CodeOffset
+ if (DebugMode == DebugMode.Source)
+ {
+ var xSymbolReader = GetSymbolReaderForAssembly(aMethod.MethodBase.DeclaringType.Assembly);
+ if (xSymbolReader != null)
+ {
+ var xSmbMethod = xSymbolReader.GetMethod(new SymbolToken(aMethod.MethodBase.MetadataToken));
+ // This gets the Sequence Points.
+ // Sequence Points are spots that identify what the compiler/debugger says is a spot
+ // that a breakpoint can occur one. Essentially, an atomic source line in C#
+ if (xSmbMethod != null)
+ {
+ xCodeOffsets = new int[xSmbMethod.SequencePointCount];
+ var xCodeDocuments = new ISymbolDocument[xSmbMethod.SequencePointCount];
+ xCodeLineNumbers = new int[xSmbMethod.SequencePointCount];
+ var xCodeColumns = new int[xSmbMethod.SequencePointCount];
+ var xCodeEndLines = new int[xSmbMethod.SequencePointCount];
+ var xCodeEndColumns = new int[xSmbMethod.SequencePointCount];
+ xSmbMethod.GetSequencePoints(xCodeOffsets, xCodeDocuments
+ , xCodeLineNumbers, xCodeColumns, xCodeEndLines, xCodeEndColumns);
+ }
+ }
+ }
+ #endregion
+ }
+
+ protected override void MethodEnd(MethodInfo aMethod)
+ {
+ base.MethodEnd(aMethod);
+ uint xReturnSize = 0;
+ var xMethInfo = aMethod.MethodBase as System.Reflection.MethodInfo;
+ if (xMethInfo != null)
+ {
+ xReturnSize = ILOp.Align(ILOp.SizeOfType(xMethInfo.ReturnType), 4);
+ }
+ new Label(ILOp.GetMethodLabel(aMethod) + EndOfMethodLabelNameNormal);
+ new CPUx86.Move { DestinationReg = CPUx86.Registers.ECX, SourceValue = 0 };
+ var xTotalArgsSize = (from item in aMethod.MethodBase.GetParameters()
+ select (int)ILOp.Align(ILOp.SizeOfType(item.ParameterType), 4)).Sum();
+ if (!aMethod.MethodBase.IsStatic)
+ {
+ if (aMethod.MethodBase.DeclaringType.IsValueType)
+ {
+ xTotalArgsSize += 4; // only a reference is passed
+ }
+ else
+ {
+ xTotalArgsSize += (int)ILOp.Align(ILOp.SizeOfType(aMethod.MethodBase.DeclaringType), 4);
+ }
+ }
+
+ if (aMethod.PluggedMethod != null)
+ {
+ xReturnSize = 0;
+ xMethInfo = aMethod.PluggedMethod.MethodBase as System.Reflection.MethodInfo;
+ if (xMethInfo != null)
+ {
+ xReturnSize = ILOp.Align(ILOp.SizeOfType(xMethInfo.ReturnType), 4);
+ }
+ xTotalArgsSize = (from item in aMethod.PluggedMethod.MethodBase.GetParameters()
+ select (int)ILOp.Align(ILOp.SizeOfType(item.ParameterType), 4)).Sum();
+ if (!aMethod.PluggedMethod.MethodBase.IsStatic)
+ {
+ if (aMethod.PluggedMethod.MethodBase.DeclaringType.IsValueType)
+ {
+ xTotalArgsSize += 4; // only a reference is passed
+ }
+ else
+ {
+ xTotalArgsSize += (int)ILOp.Align(ILOp.SizeOfType(aMethod.PluggedMethod.MethodBase.DeclaringType), 4);
+ }
+ }
+ }
+
+ if (xReturnSize > 0)
+ {
+ //var xArgSize = (from item in aArgs
+ // let xSize = item.Size + item.Offset
+ // select xSize).FirstOrDefault();
+ //new Comment(String.Format("ReturnSize = {0}, ArgumentSize = {1}",
+ // aReturnSize,
+ // xArgSize));
+ //int xOffset = 4;
+ //if(xArgSize>0) {
+ // xArgSize -= xReturnSize;
+ // xOffset = xArgSize;
+ //}
+ var xOffset = GetResultCodeOffset(xReturnSize, (uint)xTotalArgsSize);
+ for (int i = 0; i < xReturnSize / 4; i++)
+ {
+ new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX };
+ new CPUx86.Move
+ {
+ DestinationReg = CPUx86.Registers.EBP,
+ DestinationIsIndirect = true,
+ DestinationDisplacement = (int)(xOffset + ((i + 0) * 4)),
+ SourceReg = Registers.EAX
+ };
+ // new CPUx86.Move {
+ // DestinationReg = CPUx86.Registers.EBP,
+ // DestinationIsIndirect = true,
+ // DestinationDisplacement = (int)(xOffset + ((i + 1) * 4) + 4 - xReturnSize),
+ // SourceReg = Registers.EAX
+ // };
+ }
+ // extra stack space is the space reserved for example when a "public static int TestMethod();" method is called, 4 bytes is pushed, to make room for result;
+ }
+ new Label(ILOp.GetMethodLabel(aMethod) + EndOfMethodLabelNameException);
+ //for (int i = 0; i < aLocAllocItemCount; i++) {
+ // new CPUx86.Call { DestinationLabel = aHeapFreeLabel };
+ //}
+ //if (aDebugMode && aIsNonDebuggable) {
+ // new CPUx86.Call { DestinationLabel = "DebugPoint_DebugResume" };
+ //}
+
+ //if ((from xLocal in aLocals
+ // where xLocal.IsReferenceType
+ // select 1).Count() > 0 || (from xArg in aArgs
+ // where xArg.IsReferenceType
+ // select 1).Count() > 0) {
+ // new CPUx86.Push { DestinationReg = Registers.ECX };
+ // //foreach (MethodInformation.Variable xLocal in aLocals) {
+ // // if (xLocal.IsReferenceType) {
+ // // Op.Ldloc(aAssembler,
+ // // xLocal,
+ // // false,
+ // // aGetStorageSizeDelegate(xLocal.VariableType));
+ // // new CPUx86.Call { DestinationLabel = aDecRefLabel };
+ // // }
+ // //}
+ // //foreach (MethodInformation.Argument xArg in aArgs) {
+ // // if (xArg.IsReferenceType) {
+ // // Op.Ldarg(aAssembler,
+ // // xArg,
+ // // false);
+ // // //, aGetStorageSizeDelegate(xArg.ArgumentType)
+ // // new CPUx86.Call { DestinationLabel = aDecRefLabel };
+ // // }
+ // //}
+ // // todo: add GC code
+ // new CPUx86.Pop { DestinationReg = CPUx86.Registers.ECX };
+ //}
+ if (aMethod.MethodAssembler == null && aMethod.PlugMethod == null)
+ {
+ var xBody = aMethod.MethodBase.GetMethodBody();
+ if (xBody != null)
+ {
+ for (int j = xBody.LocalVariables.Count - 1; j >= 0; j--)
+ {
+ int xLocalSize = (int)ILOp.Align(ILOp.SizeOfType(xBody.LocalVariables[j].LocalType), 4);
+ new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = (uint)xLocalSize };
+ }
+ }
+ }
+ //new CPUx86.Add(CPUx86.Registers_Old.ESP, "0x4");
+ //new CPUx86.Compare { DestinationReg = Registers.EBP, SourceReg = Registers.ESP };
+ //new CPUx86.ConditionalJump { Condition = ConditionalTestEnum.Equal, DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName(aMethod.MethodBase) + EndOfMethodLabelNameException + "__2" };
+ //new CPUx86.Xchg { DestinationReg = Registers.BX, SourceReg = Registers.BX };
+ //new CPUx86.Halt();
+ // TODO: not nice coding, still a test
+ //new CPUx86.Move { DestinationReg = Registers.ESP, SourceReg = Registers.EBP };
+ new Label(ILOp.GetMethodLabel(aMethod) + EndOfMethodLabelNameException + "__2");
+ new CPUx86.Pop { DestinationReg = CPUx86.Registers.EBP };
+ var xRetSize = ((int)xTotalArgsSize) - ((int)xReturnSize);
+ if (xRetSize < 0)
+ {
+ xRetSize = 0;
+ }
+ WriteDebug(aMethod.MethodBase, (uint)xRetSize, IL.Call.GetStackSizeToReservate(aMethod.MethodBase));
+ new CPUx86.Return { DestinationValue = (uint)xRetSize };
+ }
+
+ public static uint GetResultCodeOffset(uint aResultSize, uint aTotalArgumentSize)
+ {
+ uint xOffset = 8;
+ if ((aTotalArgumentSize > 0) && (aTotalArgumentSize >= aResultSize))
+ {
+ xOffset += aTotalArgumentSize;
+ xOffset -= aResultSize;
+ }
+ return xOffset;
+ }
+
+ private static ISymbolReader GetSymbolReaderForAssembly(Assembly aAssembly)
+ {
try
{
- xMLSymbol.AssemblyFile = aMethod.MethodBase.DeclaringType.Assembly.Location;
+ return SymbolAccess.GetReaderForFile(aAssembly.Location);
}
catch (NotSupportedException)
{
- xMLSymbol.AssemblyFile = "DYNAMIC: " + aMethod.MethodBase.DeclaringType.Assembly.FullName;
+ return null;
}
- xMLSymbol.MethodToken = aMethod.MethodBase.MetadataToken;
- xMLSymbol.TypeToken = aMethod.MethodBase.DeclaringType.MetadataToken;
- xMLSymbol.ILOffset = aOpCode.Position;
- mSymbols.Add(xMLSymbol);
}
- #endregion
- EmitTracer(aMethod, aOpCode, aMethod.MethodBase.DeclaringType.Namespace, xCodeOffsets);
- }
- public TraceAssemblies TraceAssemblies;
- public DebugMode DebugMode;
+ protected override void MethodBegin(string aMethodName)
+ {
+ base.MethodBegin(aMethodName);
+ new Label(aMethodName);
+ new Push { DestinationReg = Registers.EBP };
+ new Move { DestinationReg = Registers.EBP, SourceReg = Registers.ESP };
+ xCodeOffsets = new int[0];
+ }
- protected void EmitTracer(MethodInfo aMethod, ILOpCode aOp, string aNamespace, int[] aCodeOffsets) {
- // NOTE - These if statements can be optimized down - but clarity is
- // more importnat the optimizations would not offer much benefit
+ protected override void MethodEnd(string aMethodName)
+ {
+ base.MethodEnd(aMethodName);
+ new Label("_END_OF_" + aMethodName);
+ new CPUx86.Pop { DestinationReg = CPUx86.Registers.EBP };
+ new CPUx86.Return();
+ }
- // Determine if a new DebugStub should be emitted
- //bool xEmit = false;
- // Skip NOOP's so we dont have breakpoints on them
- //TODO: Each IL op should exist in IL, and descendants in IL.X86.
- // Because of this we have this hack
- if (aOp.OpCode == ILOpCode.Code.Nop) {
- return;
- } else if (DebugMode == DebugMode.None) {
- return;
- } else if (DebugMode == DebugMode.Source) {
- // If the current position equals one of the offsets, then we have
- // reached a new atomic C# statement
- if (aCodeOffsets != null) {
- var xIndex = Array.IndexOf(aCodeOffsets, aOp.Position);
- if (xIndex == -1) {
+ private static HashSet mDebugLines = new HashSet();
+ private static void WriteDebug(MethodBase aMethod, uint aSize, uint aSize2)
+ {
+ var xLine = String.Format("{0}\t{1}\t{2}", MethodInfoLabelGenerator.GenerateFullName(aMethod), aSize, aSize2);
+
+ }
+ private List mSymbols = new List();
+
+ // These are all temp functions until we move to the new assembler.
+ // They are used to clean up the old assembler slightly while retaining compatibiltiy for now
+ public static string TmpPosLabel(MethodInfo aMethod, int aOffset)
+ {
+ // todo: fix to be small again.
+ return ILOp.GetLabel(aMethod, aOffset);
+ //TODO: Change to Hex output, will be smaller and slightly faster for NASM
+ //return "POS_" + aMethod.UID + "_" + aOffset;
+ }
+
+ public static string TmpPosLabel(MethodInfo aMethod, ILOpCode aOpCode)
+ {
+ return TmpPosLabel(aMethod, aOpCode.Position);
+ }
+
+ public static string TmpBranchLabel(MethodInfo aMethod, ILOpCode aOpCode)
+ {
+ return TmpPosLabel(aMethod, ((ILOpCodes.OpBranch)aOpCode).Value);
+ }
+
+ protected override void BeforeOp(MethodInfo aMethod, ILOpCode aOpCode)
+ {
+ base.BeforeOp(aMethod, aOpCode);
+ new Label(TmpPosLabel(aMethod, aOpCode));
+ #region Collection debug information
+ if (mSymbols != null)
+ {
+ var xMLSymbol = new DebugInfo.MLDebugSymbol();
+ xMLSymbol.LabelName = TmpPosLabel(aMethod, aOpCode);
+ xMLSymbol.MethodName = aMethod.MethodBase.GetFullName();
+ int xStackSize = (from item in mAssembler.Stack
+ let xSize = (item.Size % 4 == 0)
+ ? item.Size
+ : (item.Size + (4 - (item.Size % 4)))
+ select xSize).Sum();
+ xMLSymbol.StackDifference = -1;
+ if (aMethod.MethodBase != null)
+ {
+ var xBody = aMethod.MethodBase.GetMethodBody();
+ if (xBody != null)
+ {
+ var xLocalsSize = (from item in xBody.LocalVariables
+ select (int)ILOp.Align(ILOp.SizeOfType(item.LocalType), 4)).Sum();
+ xMLSymbol.StackDifference = xLocalsSize + xStackSize;
+ }
+ }
+ try
+ {
+ xMLSymbol.AssemblyFile = aMethod.MethodBase.DeclaringType.Assembly.Location;
+ }
+ catch (NotSupportedException)
+ {
+ xMLSymbol.AssemblyFile = "DYNAMIC: " + aMethod.MethodBase.DeclaringType.Assembly.FullName;
+ }
+ xMLSymbol.MethodToken = aMethod.MethodBase.MetadataToken;
+ xMLSymbol.TypeToken = aMethod.MethodBase.DeclaringType.MetadataToken;
+ xMLSymbol.ILOffset = aOpCode.Position;
+ mSymbols.Add(xMLSymbol);
+ }
+ #endregion
+ EmitTracer(aMethod, aOpCode, aMethod.MethodBase.DeclaringType.Namespace, xCodeOffsets);
+ }
+
+ public TraceAssemblies TraceAssemblies;
+ public DebugMode DebugMode;
+
+ protected void EmitTracer(MethodInfo aMethod, ILOpCode aOp, string aNamespace, int[] aCodeOffsets)
+ {
+ // NOTE - These if statements can be optimized down - but clarity is
+ // more importnat the optimizations would not offer much benefit
+
+ // Determine if a new DebugStub should be emitted
+ //bool xEmit = false;
+ // Skip NOOP's so we dont have breakpoints on them
+ //TODO: Each IL op should exist in IL, and descendants in IL.X86.
+ // Because of this we have this hack
+ if (aOp.OpCode == ILOpCode.Code.Nop)
+ {
+ return;
+ }
+ else if (DebugMode == DebugMode.None)
+ {
+ return;
+ }
+ else if (DebugMode == DebugMode.Source)
+ {
+ // If the current position equals one of the offsets, then we have
+ // reached a new atomic C# statement
+ if (aCodeOffsets != null)
+ {
+ var xIndex = Array.IndexOf(aCodeOffsets, aOp.Position);
+ if (xIndex == -1)
+ {
+ return;
+ }
+ // 0xFEEFEE means hiddenline -> we dont want to stop there
+ if (xCodeLineNumbers[xIndex] == 0xFEEFEE)
+ {
+ return;
+ }
+ }
+ }
+
+ // Check options for Debug Level
+ // Set based on TracedAssemblies
+ if (TraceAssemblies == TraceAssemblies.Cosmos || TraceAssemblies == TraceAssemblies.User)
+ {
+ if (aNamespace.StartsWith("System.", StringComparison.InvariantCultureIgnoreCase))
+ {
return;
}
- // 0xFEEFEE means hiddenline -> we dont want to stop there
- if (xCodeLineNumbers[xIndex] == 0xFEEFEE)
+ else if (aNamespace.ToLower() == "system")
+ {
+ return;
+ }
+ else if (aNamespace.StartsWith("Microsoft.", StringComparison.InvariantCultureIgnoreCase))
{
return;
}
}
+ if (TraceAssemblies == TraceAssemblies.User)
+ {
+ //TODO: Maybe an attribute that could be used to turn tracing on and off
+ //TODO: This doesnt match Cosmos.Kernel exact vs Cosmos.Kernel., so a user
+ // could do Cosmos.KernelMine and it will fail. Need to fix this
+ if (aNamespace.StartsWith("Cosmos.Kernel", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return;
+ }
+ else if (aNamespace.StartsWith("Cosmos.Sys", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return;
+ }
+ else if (aNamespace.StartsWith("Cosmos.Hardware", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return;
+ }
+ else if (aNamespace.StartsWith("Cosmos.IL2CPU", StringComparison.InvariantCultureIgnoreCase))
+ {
+ return;
+ }
+ }
+ // If we made it this far, emit the Tracer
+ new CPUx86.Call { DestinationLabel = "DebugStub_TracerEntry" };
}
- // Check options for Debug Level
- // Set based on TracedAssemblies
- if (TraceAssemblies == TraceAssemblies.Cosmos || TraceAssemblies == TraceAssemblies.User)
+ private int[] xCodeOffsets;
+ private int[] xCodeLineNumbers;
+ protected override void AfterOp(MethodInfo aMethod, ILOpCode aOpCode)
{
- if (aNamespace.StartsWith("System.", StringComparison.InvariantCultureIgnoreCase))
+ base.AfterOp(aMethod, aOpCode);
+ var xContents = "";
+ foreach (var xStackItem in mAssembler.Stack)
{
- return;
+ xContents += ILOp.Align((uint)xStackItem.Size, 4);
+ xContents += ", ";
}
- else if (aNamespace.ToLower() == "system")
+ if (xContents.EndsWith(", "))
{
- return;
- }
- else if (aNamespace.StartsWith("Microsoft.", StringComparison.InvariantCultureIgnoreCase))
- {
- return;
+ xContents = xContents.Substring(0, xContents.Length - 2);
}
+ new Comment("Stack contains " + mAssembler.Stack.Count + " items: (" + xContents + ")");
}
- if (TraceAssemblies == TraceAssemblies.User)
- {
- //TODO: Maybe an attribute that could be used to turn tracing on and off
- //TODO: This doesnt match Cosmos.Kernel exact vs Cosmos.Kernel., so a user
- // could do Cosmos.KernelMine and it will fail. Need to fix this
- if (aNamespace.StartsWith("Cosmos.Kernel", StringComparison.InvariantCultureIgnoreCase))
- {
- return;
- }
- else if (aNamespace.StartsWith("Cosmos.Sys", StringComparison.InvariantCultureIgnoreCase))
- {
- return;
- }
- else if (aNamespace.StartsWith("Cosmos.Hardware", StringComparison.InvariantCultureIgnoreCase))
- {
- return;
- }
- else if (aNamespace.StartsWith("Cosmos.IL2CPU", StringComparison.InvariantCultureIgnoreCase))
- {
- return;
- }
- }
- // If we made it this far, emit the Tracer
- new CPUx86.Call { DestinationLabel = "DebugStub_TracerEntry" };
- }
- private int[] xCodeOffsets;
- private int[] xCodeLineNumbers;
- protected override void AfterOp(MethodInfo aMethod, ILOpCode aOpCode) {
- base.AfterOp(aMethod, aOpCode);
- var xContents = "";
- foreach (var xStackItem in mAssembler.Stack)
- {
- xContents += ILOp.Align((uint)xStackItem.Size, 4);
- xContents += ", ";
- }
- if (xContents.EndsWith(", ")) {
- xContents = xContents.Substring(0, xContents.Length - 2);
- }
- new Comment("Stack contains " + mAssembler.Stack.Count + " items: (" + xContents + ")");
- }
-
- public void WriteDebugSymbols(string DebugSymbolsFile)
- {
- if (mSymbols.Count > 0)
+ public DebugInfo DebugInfo
{
- MLDebugSymbol.WriteSymbolsListToFile(mSymbols, DebugSymbolsFile);
+ get;
+ set;
+ }
+
+ public void FinalizeDebugInfo()
+ {
+ this.DebugInfo.WriteSymbolsListToFile(mSymbols);
}
}
- }
-}
+}
\ No newline at end of file