This commit is contained in:
mterwoord_cp 2014-07-13 22:33:53 +00:00
parent 03366efdf7
commit e9a2fb40df
8 changed files with 221 additions and 178 deletions

View file

@ -0,0 +1,6 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ObjectCreationAsStatement/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Locals/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="x" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Parameters/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="a" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="m" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="m" Suffix="" Style="AaBb" /&gt;</s:String></wpf:ResourceDictionary>

View file

@ -8,6 +8,7 @@ using System.Runtime.InteropServices;
using System.Text; using System.Text;
using Cosmos.Assembler; using Cosmos.Assembler;
using Cosmos.Assembler.x86; using Cosmos.Assembler.x86;
using Cosmos.Assembler.x86._486AndUp;
using Cosmos.Build.Common; using Cosmos.Build.Common;
using Cosmos.Debug.Common; using Cosmos.Debug.Common;
using Cosmos.IL2CPU.Plugs; using Cosmos.IL2CPU.Plugs;
@ -66,10 +67,6 @@ namespace Cosmos.IL2CPU
new Comment("Type: " + aMethod.MethodBase.DeclaringType.ToString()); new Comment("Type: " + aMethod.MethodBase.DeclaringType.ToString());
new Comment("Name: " + aMethod.MethodBase.Name); new Comment("Name: " + aMethod.MethodBase.Name);
new Comment("Plugged: " + (aMethod.PlugMethod == null ? "No" : "Yes")); new Comment("Plugged: " + (aMethod.PlugMethod == null ? "No" : "Yes"));
if (aMethod.MethodBase.Name == "GetFatEntry")
{
Console.Write("");
}
// for now: // for now:
var shouldIncludeArgAndLocalsComment = true; var shouldIncludeArgAndLocalsComment = true;
if (shouldIncludeArgAndLocalsComment) if (shouldIncludeArgAndLocalsComment)
@ -460,6 +457,8 @@ namespace Cosmos.IL2CPU
} }
else else
{ {
// now emit the actual assembler code for this method.
//Conditions under which we should emit an INT3 instead of a plceholder NOP: //Conditions under which we should emit an INT3 instead of a plceholder NOP:
/* - First instruction in a Method / Loop / If / Else etc. /* - First instruction in a Method / Loop / If / Else etc.
* -- In essence, whenever there is a opening { * -- In essence, whenever there is a opening {
@ -467,8 +466,63 @@ namespace Cosmos.IL2CPU
* -- So only insert an INT3 when we are about to insert a NOP that came from IL code * -- So only insert an INT3 when we are about to insert a NOP that came from IL code
*/ */
/* We group opcodes together by logical statement. Each statement will have its logical stack cleared.
* Also, this lets us do optimizations later on.
*/
bool emitINT3 = true; bool emitINT3 = true;
foreach (var xOpCode in aOpCodes) DebugInfo.SequencePoint xPreviousSequencePoint = null;
var xCurrentGroup = new List<ILOpCode>();
foreach (var xRawOpcode in aOpCodes)
{
var xSP = mSequences.FirstOrDefault(q => q.Offset == xRawOpcode.Position && q.LineStart != 0xFEEFEE);
var hasNewSP = false;
// detect if we're at a new statement.
if (xPreviousSequencePoint == null && xSP != null)
{
}
if (xSP != null && xCurrentGroup.Count > 0)
{
EmitInstructions(aMethod, xCurrentGroup, ref emitINT3);
xCurrentGroup.Clear();
xPreviousSequencePoint = xSP;
}
xCurrentGroup.Add(xRawOpcode);
}
if (xCurrentGroup.Count > 0)
{
EmitInstructions(aMethod, xCurrentGroup, ref emitINT3);
}
}
MethodEnd(aMethod);
}
private void BeforeEmitInstructions(MethodInfo aMethod, List<ILOpCode> aCurrentGroup)
{
// do optimizations
}
private void AfterEmitInstructions(MethodInfo aMethod, List<ILOpCode> aCurrentGroup)
{
// do optimizations
if (Assembler.Stack.Count > 0)
{
if (mDebugStackErrors)
{
Console.WriteLine("StackCorruption in Analytical stack:");
Console.WriteLine("- Method: {0}", aMethod.MethodBase.GetFullName());
Console.WriteLine("- Last ILOpCode offset: {0}", aCurrentGroup.Last().Position.ToString("X"));
}
}
}
private static bool mDebugStackErrors = true;
private void EmitInstructions(MethodInfo aMethod, List<ILOpCode> xCurrentGroup, ref bool emitINT3)
{
new Comment(String.Format("New Group Offset {0} - Offset {1}", xCurrentGroup.First().Position.ToString("X"), xCurrentGroup.Last().Position.ToString("X")));
BeforeEmitInstructions(aMethod, xCurrentGroup);
var xFirstInstruction = true;
foreach (var xOpCode in xCurrentGroup)
{ {
ushort xOpCodeVal = (ushort) xOpCode.OpCode; ushort xOpCodeVal = (ushort) xOpCode.OpCode;
ILOp xILOp; ILOp xILOp;
@ -485,14 +539,17 @@ namespace Cosmos.IL2CPU
//Only emit INT3 as per conditions above... //Only emit INT3 as per conditions above...
bool INT3Emitted = false; bool INT3Emitted = false;
BeforeOp(aMethod, xOpCode, emitINT3, out INT3Emitted); BeforeOp(aMethod, xOpCode, emitINT3, out INT3Emitted, xFirstInstruction);
xFirstInstruction = false;
//Emit INT3 on the first non-NOP instruction immediately after a NOP //Emit INT3 on the first non-NOP instruction immediately after a NOP
// - This is because TracePoints for NOP are automatically ignored in code called below this // - This is because TracePoints for NOP are automatically ignored in code called below this
emitINT3 = (emitINT3 && !INT3Emitted) || xILOp is Cosmos.IL2CPU.X86.IL.Nop; emitINT3 = (emitINT3 && !INT3Emitted) || xILOp is Cosmos.IL2CPU.X86.IL.Nop;
new Comment(xILOp.ToString()); new Comment(xILOp.ToString());
var xNextPosition = xOpCode.Position + 1; var xNextPosition = xOpCode.Position + 1;
#region Exception handling support code #region Exception handling support code
ExceptionHandlingClause xCurrentHandler = null; ExceptionHandlingClause xCurrentHandler = null;
var xBody = aMethod.MethodBase.GetMethodBody(); var xBody = aMethod.MethodBase.GetMethodBody();
// todo: add support for nested handlers using a stack or so.. // todo: add support for nested handlers using a stack or so..
@ -553,7 +610,9 @@ namespace Cosmos.IL2CPU
} }
} }
} }
#endregion #endregion
var xNeedsExceptionPush = (xCurrentHandler != null) && (((xCurrentHandler.HandlerOffset > 0 && xCurrentHandler.HandlerOffset == xOpCode.Position) || ((xCurrentHandler.Flags & ExceptionHandlingClauseOptions.Filter) > 0 && xCurrentHandler.FilterOffset > 0 && xCurrentHandler.FilterOffset == xOpCode.Position)) && (xCurrentHandler.Flags == ExceptionHandlingClauseOptions.Clause)); var xNeedsExceptionPush = (xCurrentHandler != null) && (((xCurrentHandler.HandlerOffset > 0 && xCurrentHandler.HandlerOffset == xOpCode.Position) || ((xCurrentHandler.Flags & ExceptionHandlingClauseOptions.Filter) > 0 && xCurrentHandler.FilterOffset > 0 && xCurrentHandler.FilterOffset == xOpCode.Position)) && (xCurrentHandler.Flags == ExceptionHandlingClauseOptions.Clause));
if (xNeedsExceptionPush) if (xNeedsExceptionPush)
{ {
@ -566,8 +625,7 @@ namespace Cosmos.IL2CPU
AfterOp(aMethod, xOpCode); AfterOp(aMethod, xOpCode);
//mLog.WriteLine( " end: " + Stack.Count.ToString() ); //mLog.WriteLine( " end: " + Stack.Count.ToString() );
} }
} AfterEmitInstructions(aMethod, xCurrentGroup);
MethodEnd(aMethod);
} }
protected void InitILOps() protected void InitILOps()
@ -1177,7 +1235,7 @@ namespace Cosmos.IL2CPU
new Comment("Stack contains " + Assembler.Stack.Count + " items: (" + xContents + ")"); new Comment("Stack contains " + Assembler.Stack.Count + " items: (" + xContents + ")");
} }
protected void BeforeOp(MethodInfo aMethod, ILOpCode aOpCode, bool emitInt3NotNop, out bool INT3Emitted) protected void BeforeOp(MethodInfo aMethod, ILOpCode aOpCode, bool emitInt3NotNop, out bool INT3Emitted, bool hasSourcePoint)
{ {
string xLabel = TmpPosLabel(aMethod, aOpCode); string xLabel = TmpPosLabel(aMethod, aOpCode);
Assembler.CurrentIlLabel = xLabel; Assembler.CurrentIlLabel = xLabel;
@ -1211,7 +1269,7 @@ namespace Cosmos.IL2CPU
DebugInfo.AddSymbols(mSymbols, false); DebugInfo.AddSymbols(mSymbols, false);
bool INT3PlaceholderEmitted = false; bool INT3PlaceholderEmitted = false;
EmitTracer(aMethod, aOpCode, aMethod.MethodBase.DeclaringType.Namespace, emitInt3NotNop, out INT3Emitted, out INT3PlaceholderEmitted); EmitTracer(aMethod, aOpCode, aMethod.MethodBase.DeclaringType.Namespace, emitInt3NotNop, out INT3Emitted, out INT3PlaceholderEmitted, hasSourcePoint);
if (INT3Emitted || INT3PlaceholderEmitted) if (INT3Emitted || INT3PlaceholderEmitted)
{ {
@ -1223,43 +1281,43 @@ namespace Cosmos.IL2CPU
DebugInfo.AddINT3Labels(mINT3Labels); DebugInfo.AddINT3Labels(mINT3Labels);
} }
if (DebugEnabled && StackCorruptionDetection) //if (DebugEnabled && StackCorruptionDetection)
{ //{
// if debugstub is active, emit a stack corruption detection. at this point, the difference between EBP and ESP // // if debugstub is active, emit a stack corruption detection. at this point, the difference between EBP and ESP
// should be equal to the local variables sizes and the IL stack. // // should be equal to the local variables sizes and the IL stack.
// if not, we should break here. // // if not, we should break here.
// first, calculate the expected difference // // first, calculate the expected difference
var expectedDifference = aMethod.LocalVariablesSize; // var expectedDifference = aMethod.LocalVariablesSize;
foreach (var item in Assembler.Stack) // foreach (var item in Assembler.Stack)
{ // {
expectedDifference += X86.IL.Ldarg.Align(item.Size, 4); // expectedDifference += X86.IL.Ldarg.Align(item.Size, 4);
// }
// // if debugstub is active, emit a stack corruption detection. at this point EBP and ESP should have the same value.
// // if not, we should somehow break here.
// new Mov { DestinationReg = Registers.EAX, SourceReg = RegistersEnum.ESP };
// new Mov { DestinationReg = Registers.EBX, SourceReg = RegistersEnum.EBP };
// new Add { DestinationReg = Registers.EAX, SourceValue = expectedDifference };
// new Compare { SourceReg = RegistersEnum.EAX, DestinationReg = RegistersEnum.EBX };
// new ConditionalJump { Condition = ConditionalTestEnum.Equal, DestinationLabel = xLabel + ".StackCorruptionCheck_End" };
// new ClrInterruptFlag();
// // don't remove the call. It seems pointless, but we need it to retrieve the EIP value
// new Call { DestinationLabel = xLabel + ".StackCorruptionCheck_GetAddress" };
// new Assembler.Label(xLabel + ".StackCorruptionCheck_GetAddress");
// new Pop { DestinationReg = RegistersEnum.EAX };
// new Mov { DestinationRef = ElementReference.New("DebugStub_CallerEIP"), DestinationIsIndirect = true, SourceReg = RegistersEnum.EAX };
// new Call { DestinationLabel = "DebugStub_SendStackCorruptionOccurred" };
// new Halt();
// new Assembler.Label(xLabel + ".StackCorruptionCheck_End");
//}
} }
// if debugstub is active, emit a stack corruption detection. at this point EBP and ESP should have the same value. protected void EmitTracer(MethodInfo aMethod, ILOpCode aOp, string aNamespace, bool emitInt3NotNop, out bool INT3Emitted, out bool INT3PlaceholderEmitted, bool isNewSourcePoint)
// if not, we should somehow break here.
new Mov { DestinationReg = Registers.EAX, SourceReg = RegistersEnum.ESP };
new Mov { DestinationReg = Registers.EBX, SourceReg = RegistersEnum.EBP };
new Add { DestinationReg = Registers.EAX, SourceValue = expectedDifference };
new Compare { SourceReg = RegistersEnum.EAX, DestinationReg = RegistersEnum.EBX };
new ConditionalJump { Condition = ConditionalTestEnum.Equal, DestinationLabel = xLabel + ".StackCorruptionCheck_End" };
new ClrInterruptFlag();
// don't remove the call. It seems pointless, but we need it to retrieve the EIP value
new Call { DestinationLabel = xLabel + ".StackCorruptionCheck_GetAddress" };
new Assembler.Label(xLabel + ".StackCorruptionCheck_GetAddress");
new Pop { DestinationReg = RegistersEnum.EAX };
new Mov { DestinationRef = ElementReference.New("DebugStub_CallerEIP"), DestinationIsIndirect = true, SourceReg = RegistersEnum.EAX };
new Call { DestinationLabel = "DebugStub_SendStackCorruptionOccurred" };
new Halt();
new Assembler.Label(xLabel + ".StackCorruptionCheck_End");
}
}
protected void EmitTracer(MethodInfo aMethod, ILOpCode aOp, string aNamespace, bool emitInt3NotNop, out bool INT3Emitted, out bool INT3PlaceholderEmitted)
{ {
// NOTE - These if statements can be optimized down - but clarity is // NOTE - These if statements can be optimized down - but clarity is
// more important the optimizations. Furthermoer the optimazations available // more important than the optimizations. Furthermore the optimizations available
// would not offer much benefit // would not offer much benefit
// Determine if a new DebugStub should be emitted // Determine if a new DebugStub should be emitted
@ -1282,16 +1340,10 @@ namespace Cosmos.IL2CPU
{ {
// If the current position equals one of the offsets, then we have // If the current position equals one of the offsets, then we have
// reached a new atomic C# statement // reached a new atomic C# statement
var xSP = mSequences.SingleOrDefault(q => q.Offset == aOp.Position); if (!isNewSourcePoint)
if (xSP == null)
{ {
return; return;
} }
else if (xSP.LineStart == 0xFEEFEE)
{
// 0xFEEFEE means hiddenline -> we dont want to stop there
return;
}
} }
// Check if the DebugStub has been disabled for this method // Check if the DebugStub has been disabled for this method

View file

@ -17,6 +17,7 @@ namespace Cosmos.IL2CPU.X86.IL
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) public override void Execute( MethodInfo aMethod, ILOpCode aOpCode )
{ {
var xStackItem = Assembler.Stack.Pop(); var xStackItem = Assembler.Stack.Pop();
Assembler.Stack.Pop();
if( xStackItem.Size > 8 ) if( xStackItem.Size > 8 )
{ {
//EmitNotImplementedException( Assembler, GetServiceProvider(), "Cgt: StackSizes>8 not supported", CurInstructionLabel, mMethodInfo, mCurrentOffset, NextInstructionLabel ); //EmitNotImplementedException( Assembler, GetServiceProvider(), "Cgt: StackSizes>8 not supported", CurInstructionLabel, mMethodInfo, mCurrentOffset, NextInstructionLabel );

View file

@ -16,6 +16,7 @@ namespace Cosmos.IL2CPU.X86.IL
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) public override void Execute( MethodInfo aMethod, ILOpCode aOpCode )
{ {
var xStackItem = Assembler.Stack.Pop(); var xStackItem = Assembler.Stack.Pop();
Assembler.Stack.Pop();
if( xStackItem.Size > 8 ) if( xStackItem.Size > 8 )
{ {
throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Clt_Un.cs->Error: StackSizes > 8 not supported"); throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Clt_Un.cs->Error: StackSizes > 8 not supported");

View file

@ -10,11 +10,17 @@ namespace Cosmos.IL2CPU.X86.IL
{ {
} }
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
{
//TODO: Return //TODO: Return
Jump_End(aMethod); Jump_End(aMethod);
// Need to jump to end of method. Assembler can emit this label for now // Need to jump to end of method. Assembler can emit this label for now
//new CPU.Jump { DestinationLabel = MethodFooterOp.EndOfMethodLabelNameNormal }; //new CPU.Jump { DestinationLabel = MethodFooterOp.EndOfMethodLabelNameNormal };
var methodInf = aMethod.MethodBase as System.Reflection.MethodInfo;
if (methodInf != null && methodInf.ReturnType != typeof (void))
{
Assembler.Stack.Pop();
}
} }
} }
} }

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using SR = System.Reflection; using SR = System.Reflection;
@ -10,6 +11,7 @@ namespace Cosmos.IL2CPU {
// Include reference to ILOp, the scanner should do that // Include reference to ILOp, the scanner should do that
// Include referense to System.Reflection.Emit, this is metadata // Include referense to System.Reflection.Emit, this is metadata
// only needed by reader and not ILOpCode // only needed by reader and not ILOpCode
//[DebuggerDisplay("IL_{Position}{:{OpCode}")]
public abstract class ILOpCode { public abstract class ILOpCode {
public enum Code : ushort { public enum Code : ushort {
@ -258,5 +260,9 @@ namespace Cosmos.IL2CPU {
CurrentExceptionHandler = aCurrentExceptionHandler; CurrentExceptionHandler = aCurrentExceptionHandler;
} }
public override string ToString()
{
return String.Format("IL_{0}: {1}", Position.ToString("X4"), OpCode);
}
} }
} }

View file

@ -16,36 +16,6 @@ namespace Cosmos.IL2CPU
{ {
public delegate void LogExceptionDelegate(Exception e); public delegate void LogExceptionDelegate(Exception e);
// This is necessary because HashSet and Dictionary
// have troubles when different types of objects are stored
// in them. I dont remember the exact problem, but something
// with how it compares objects. ie when HashSet<object> is used, this is necessary.
/*public class HashcodeComparer<T> : IEqualityComparer<T> {
public bool Equals(T x, T y) {
return internalEqualsSinceNET40(x, y);// x.GetHashCode() == y.GetHashCode();
}
public bool internalEqualsSinceNET40(T left, T right)
{
var methodDeclaringType = left.GetType().GetMethod("get_DeclaringType");
var leftDeclaringType = methodDeclaringType.Invoke(left, null);
var method = right.GetType().GetMethod("get_DeclaringType");
var rightDeclaringType = method.Invoke(right, null);
if (left.ToString() == right.ToString()
&& leftDeclaringType == rightDeclaringType)
{
return true;
}
return false;
}
public int GetHashCode(T obj) {
return obj.GetHashCode();
}
}*/
public class ScannerQueueItem public class ScannerQueueItem
{ {
public _MemberInfo Item; public _MemberInfo Item;

View file

@ -29,6 +29,7 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit> <Prefer32Bit>false</Prefer32Bit>
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>