mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-20 04:48:53 +00:00
+ bootstrap configuration builds again
+ debug info handling is refactored into 1 class
This commit is contained in:
parent
5739b0dd02
commit
415f528359
12 changed files with 740 additions and 549 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@
|
|||
<Compile Include="MakeISO.cs" />
|
||||
<Compile Include="NAsm.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ReadNAsmMapToCosmosMap.cs" />
|
||||
<Compile Include="ReadNAsmMapToDebugInfo.cs" />
|
||||
<Compile Include="TestClass.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@
|
|||
Condition="$(IsELF) == 'true'"/>
|
||||
<Delete Files="$(TargetDir)$(MSBuildProjectName).obj" Condition="$(IsELF) == 'true'"/>
|
||||
<ExtractMapFromElfFile InputFile="$(TargetDir)$(MSBuildProjectName).bin"
|
||||
OutputFile="$(TargetDir)$(MSBuildProjectName).cpdb"
|
||||
DebugInfoFile="$(TargetDir)$(MSBuildProjectName).cpdb"
|
||||
WorkingDir="$(TargetDir)"
|
||||
CosmosBuildDir="$(CosmosDir)\Build"
|
||||
Condition="$(IsELF) == 'true'"/>
|
||||
|
|
@ -69,7 +69,7 @@
|
|||
|
||||
<!--binary only-->
|
||||
<ReadNAsmMapToCosmosMap InputBaseDir="$(TargetDir)"
|
||||
OutputFile="$(TargetDir)$(MSBuildProjectName).cpdb"
|
||||
DebugInfoFile="$(TargetDir)$(MSBuildProjectName).cpdb"
|
||||
Condition="$(IsELF) == 'false'"/>
|
||||
<!--end of binary only-->
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -88,6 +88,7 @@
|
|||
<Compile Include="DebugConnectorSerial.cs" />
|
||||
<Compile Include="DebugConnectorStream.cs" />
|
||||
<Compile Include="DebugConnectorTCPServer.cs" />
|
||||
<Compile Include="DebugInfo.cs" />
|
||||
<Compile Include="DebugSymbol.cs" />
|
||||
<Compile Include="KeyState.cs" />
|
||||
<Compile Include="NameValueCollectionHelper.cs" />
|
||||
|
|
|
|||
263
source2/Debug/Cosmos.Debug.Common/DebugInfo.cs
Normal file
263
source2/Debug/Cosmos.Debug.Common/DebugInfo.cs
Normal file
|
|
@ -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<MLDebugSymbol> 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<MLDebugSymbol> 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<uint, string> oAddressLabelMappings, out IDictionary<string, uint> oLabelAddressMappings)
|
||||
{
|
||||
oAddressLabelMappings = new Dictionary<uint, string>();
|
||||
oLabelAddressMappings = new Dictionary<string, uint>();
|
||||
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<uint, String> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MLDebugSymbol> 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<MLDebugSymbol> 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;
|
||||
|
|
|
|||
|
|
@ -50,51 +50,6 @@ namespace Cosmos.Debug.Common
|
|||
set;
|
||||
}
|
||||
|
||||
public static void WriteToFile(SortedList<uint, String> 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<uint, string> oAddressLabelMappings, out IDictionary<string, uint> oLabelAddressMappings)
|
||||
{
|
||||
oAddressLabelMappings = new Dictionary<uint, string>();
|
||||
oLabelAddressMappings = new Dictionary<string, uint>();
|
||||
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<uint,String> 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<uint, string> aAddressLabelMappings, IDictionary<string, uint> aLabelAddressMappings, string aDebugFile) {
|
||||
var xSymbolsList = new List<MLDebugSymbol>();
|
||||
MLDebugSymbol.ReadSymbolsListFromFile(xSymbolsList, aDebugFile);
|
||||
public static SourceInfos GetSourceInfo(IDictionary<uint, string> aAddressLabelMappings, IDictionary<string, uint> aLabelAddressMappings, DebugInfo debugInfo) {
|
||||
var xSymbolsList = new List<DebugInfo.MLDebugSymbol>();
|
||||
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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -189,24 +189,29 @@ namespace Cosmos.Debug.VSDebugEngine {
|
|||
|
||||
IDictionary<uint, string> xAddressLabelMappings;
|
||||
IDictionary<string, uint> 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 {
|
||||
|
|
|
|||
|
|
@ -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<string> mDebugLines = new HashSet<string>();
|
||||
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<MLDebugSymbol> mSymbols = new List<MLDebugSymbol>();
|
||||
|
||||
// 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<string> mDebugLines = new HashSet<string>();
|
||||
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<DebugInfo.MLDebugSymbol> mSymbols = new List<DebugInfo.MLDebugSymbol>();
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue