511 lines
17 KiB
C#
511 lines
17 KiB
C#
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// File: Debug.cs
|
|
//
|
|
// Note:
|
|
//
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Diagnostics;
|
|
using System.Reflection;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading;
|
|
|
|
using Microsoft.Singularity.Hal;
|
|
using Microsoft.Singularity.Io;
|
|
using Microsoft.Singularity.Loader;
|
|
using Microsoft.Singularity.X86;
|
|
|
|
namespace Microsoft.Singularity
|
|
{
|
|
[NoCCtor]
|
|
[CLSCompliant(false)]
|
|
public class DebugStub
|
|
{
|
|
public static ulong perfCounter0;
|
|
public static ulong perfCounter1;
|
|
public static ulong perfCounter2;
|
|
public static ulong perfCounter3;
|
|
public static ulong perfCounter4;
|
|
public static ulong perfCounter5;
|
|
public static ulong perfCounter6;
|
|
public static ulong perfCounter7;
|
|
public static ulong perfCounter8;
|
|
public static ulong perfCounter9;
|
|
public static ulong perfCounter10;
|
|
public static ulong perfCounter11;
|
|
public static ulong perfCounter12;
|
|
public static ulong perfCounter13;
|
|
public static ulong perfCounter14;
|
|
public static ulong perfCounter15;
|
|
|
|
/////////////////////////////////////////////////////// Print Methods.
|
|
//
|
|
[NoHeapAllocation]
|
|
public static void Print(byte value)
|
|
{
|
|
Print("{0:x2}", __arglist(value));
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static void Print(ushort value)
|
|
{
|
|
Print("{0:x4}", __arglist(value));
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static void Print(uint value)
|
|
{
|
|
Print("{0:x8}", __arglist(value));
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static void Print(ulong value)
|
|
{
|
|
Print("{0:x}", __arglist(value));
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static void Print(UIntPtr value)
|
|
{
|
|
Print("{0:x8}", __arglist(value));
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static void Print(sbyte value)
|
|
{
|
|
Print("{0}", __arglist(value));
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static void Print(short value)
|
|
{
|
|
Print("{0}", __arglist(value));
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static void Print(int value)
|
|
{
|
|
Print("{0}", __arglist(value));
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static void Print(long value)
|
|
{
|
|
Print("{0}", __arglist(value));
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static void Print(String value)
|
|
{
|
|
if (value != null) {
|
|
Print(value, new ArgIterator());
|
|
}
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static void Print(String format, __arglist)
|
|
{
|
|
Print(format, new ArgIterator(__arglist));
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static unsafe void Print(String format, ArgIterator args)
|
|
{
|
|
char *buffer;
|
|
int length;
|
|
int used = 0;
|
|
|
|
PrintBegin(out buffer, out length);
|
|
try {
|
|
if (buffer != null) {
|
|
used = String.LimitedFormatTo(format, args, buffer, length);
|
|
}
|
|
}
|
|
finally {
|
|
PrintComplete(buffer, used);
|
|
}
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static void Write(String value)
|
|
{
|
|
if (value != null) {
|
|
Write(value, new ArgIterator());
|
|
}
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static void Write(String format, __arglist)
|
|
{
|
|
Print(format, new ArgIterator(__arglist));
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static unsafe void Write(String format, ArgIterator args)
|
|
{
|
|
char *buffer;
|
|
int length;
|
|
int used = 0;
|
|
|
|
PrintBegin(out buffer, out length);
|
|
try {
|
|
if (buffer != null) {
|
|
used = String.LimitedFormatTo(format, args, buffer, length);
|
|
}
|
|
}
|
|
finally {
|
|
PrintComplete(buffer, used);
|
|
}
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static void WriteLine()
|
|
{
|
|
WriteLine("", new ArgIterator());
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static void WriteLine(String value)
|
|
{
|
|
if (value != null) {
|
|
WriteLine(value, new ArgIterator());
|
|
}
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static void WriteLine(String format, __arglist)
|
|
{
|
|
WriteLine(format, new ArgIterator(__arglist));
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static unsafe void WriteLine(String format, ArgIterator args)
|
|
{
|
|
char *buffer;
|
|
int length;
|
|
int used = 0;
|
|
|
|
PrintBegin(out buffer, out length);
|
|
try {
|
|
if (buffer != null) {
|
|
used = String.LimitedFormatTo(format, args, buffer, length);
|
|
if (used < length) {
|
|
buffer[used++] = '\n';
|
|
}
|
|
}
|
|
}
|
|
finally {
|
|
PrintComplete(buffer, used);
|
|
}
|
|
}
|
|
|
|
[AccessedByRuntime("output to header : defined in halkd.cpp")]
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
[StackBound(610)]
|
|
[NoHeapAllocation]
|
|
public static extern unsafe void PrintBegin(out char * buffer, out int length);
|
|
|
|
[AccessedByRuntime("output to header : defined in halkd.cpp")]
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
[StackBound(610)]
|
|
[NoHeapAllocation]
|
|
public static extern unsafe void PrintComplete(char * buffer, int used);
|
|
|
|
[AccessedByRuntime("output to header : defined in halkd.cpp")]
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
[StackBound(610)]
|
|
[NoHeapAllocation]
|
|
public static extern unsafe void Print(char *buffer);
|
|
|
|
[AccessedByRuntime("output to header : defined in halkd.cpp")]
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
[StackBound(610)]
|
|
[NoHeapAllocation]
|
|
public static extern unsafe void Print(char *buffer, int length);
|
|
|
|
////////////////////////////////////////////////////// Assert Methods.
|
|
//
|
|
[NoHeapAllocation]
|
|
public static void NotImplemented()
|
|
{
|
|
failAssert("Not implemented.");
|
|
}
|
|
|
|
[NoHeapAllocation]
|
|
public static void NotImplemented(String msg)
|
|
{
|
|
failAssert("Not implemented: {0}", __arglist(msg));
|
|
}
|
|
|
|
[Conditional("DEBUG")]
|
|
[NoInline]
|
|
[NoHeapAllocation]
|
|
public static void NotReached()
|
|
{
|
|
failAssert("Unreachable code reached.");
|
|
}
|
|
|
|
[Conditional("DEBUG")]
|
|
[NoInline]
|
|
[NoHeapAllocation]
|
|
public static void NotReached(String msg)
|
|
{
|
|
failAssert("Unreachable code reached: ", __arglist(msg));
|
|
}
|
|
|
|
[Conditional("DEBUG")]
|
|
[NoInline]
|
|
[NoHeapAllocation]
|
|
[ManualRefCounts]
|
|
public static void Assert(bool expr)
|
|
{
|
|
if (!expr) {
|
|
failAssert(null);
|
|
}
|
|
}
|
|
|
|
[Conditional("DEBUG")]
|
|
[NoInline]
|
|
[NoHeapAllocation]
|
|
[ManualRefCounts]
|
|
public static void Deny(bool expr)
|
|
{
|
|
if (expr) {
|
|
failAssert(null);
|
|
}
|
|
}
|
|
|
|
[Conditional("DEBUG")]
|
|
[NoInline]
|
|
[NoHeapAllocation]
|
|
[ManualRefCounts]
|
|
public static void Assert(bool expr, String s)
|
|
{
|
|
if (!expr) {
|
|
failAssert(s);
|
|
}
|
|
}
|
|
|
|
[Conditional("DEBUG")]
|
|
[NoInline]
|
|
[NoHeapAllocation]
|
|
public static void Deny(bool expr, String s)
|
|
{
|
|
if (expr) {
|
|
failAssert(s);
|
|
}
|
|
}
|
|
|
|
[Conditional("DEBUG")]
|
|
[NoInline]
|
|
[NoHeapAllocation]
|
|
[ManualRefCounts]
|
|
public static void Assert(bool expr, String format, __arglist)
|
|
{
|
|
if (!expr) {
|
|
failAssert(format, new ArgIterator(__arglist));
|
|
}
|
|
}
|
|
|
|
[Conditional("DEBUG")]
|
|
[NoInline]
|
|
[NoHeapAllocation]
|
|
public static void Deny(bool expr, String format, __arglist)
|
|
{
|
|
if (expr) {
|
|
failAssert(format, new ArgIterator(__arglist));
|
|
}
|
|
}
|
|
|
|
[ManualRefCounts]
|
|
[NoHeapAllocation]
|
|
private static void failAssert(String s)
|
|
{
|
|
if (s != null) {
|
|
WriteLine("Assertion failed: {0}", __arglist(s));
|
|
}
|
|
else {
|
|
WriteLine("Assertion failed.");
|
|
}
|
|
Break();
|
|
}
|
|
|
|
[ManualRefCounts]
|
|
[NoHeapAllocation]
|
|
private static void failAssert(String format, __arglist)
|
|
{
|
|
failAssert(format, new ArgIterator(__arglist));
|
|
}
|
|
|
|
[ManualRefCounts]
|
|
[NoHeapAllocation]
|
|
private static void failAssert(String format, ArgIterator args)
|
|
{
|
|
if (format != null) {
|
|
Write("Assertion failed: ");
|
|
WriteLine(format, args);
|
|
}
|
|
else {
|
|
WriteLine("Assertion failed.");
|
|
}
|
|
Break();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////// State Methods.
|
|
//
|
|
[AccessedByRuntime("output to header : defined in halkd.cpp")]
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
[StackBound(638)]
|
|
[NoHeapAllocation]
|
|
public static extern void Break();
|
|
|
|
[AccessedByRuntime("output to header : defined in halkd.cpp")]
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
[StackBound(1024)]
|
|
[NoHeapAllocation]
|
|
internal static extern bool Trap(ref ThreadContext context, bool firstChance);
|
|
|
|
[AccessedByRuntime("output to header : defined in halkd.cpp")]
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
[StackBound(1024)]
|
|
[NoHeapAllocation]
|
|
internal static extern bool TrapForProcessorSwitch(ref ThreadContext context);
|
|
|
|
[AccessedByRuntime("output to header : defined in halkd.cpp")]
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
[StackBound(1024)]
|
|
[NoHeapAllocation]
|
|
internal static extern void AddProcessor(int cpuId);
|
|
|
|
[AccessedByRuntime("output to header : defined in halkd.cpp")]
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
[StackBound(1024)]
|
|
[NoHeapAllocation]
|
|
internal static extern void RevertToUniprocessor();
|
|
|
|
[AccessedByRuntime("output to header : defined in halkd.cpp")]
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
[StackBound(1024)]
|
|
[NoHeapAllocation]
|
|
public static extern bool PollForBreak();
|
|
|
|
[AccessedByRuntime("output to header : defined in halkd.cpp")]
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
[StackBound(1024)]
|
|
[NoHeapAllocation]
|
|
public static extern bool LoadedBinary(UIntPtr baseAddress,
|
|
UIntPtr bytes,
|
|
UIntPtr name,
|
|
uint checksum,
|
|
uint timestamp,
|
|
bool silent);
|
|
|
|
[AccessedByRuntime("output to header : defined in halkd.cpp")]
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
[StackBound(1024)]
|
|
[NoHeapAllocation]
|
|
public static extern bool LoadedBinary(UIntPtr baseAddress,
|
|
UIntPtr bytes,
|
|
String name,
|
|
uint checksum,
|
|
uint timestamp,
|
|
bool silent);
|
|
|
|
[AccessedByRuntime("output to header : defined in halkd.cpp")]
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
[StackBound(1024)]
|
|
[NoHeapAllocation]
|
|
public static extern bool UnloadedBinary(UIntPtr baseAddress,
|
|
bool silent);
|
|
|
|
[AccessedByRuntime("output to header : defined in halkd.cpp")]
|
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
[StackBound(1024)]
|
|
[NoHeapAllocation]
|
|
public static extern bool IsDebuggerPresent();
|
|
|
|
[AccessedByRuntime("output to header : defined in halkd.cpp")]
|
|
[NoHeapAllocation]
|
|
public static ulong ReadPerfCounter(uint which)
|
|
{
|
|
switch (which) {
|
|
case 0: return perfCounter0;
|
|
case 1: return perfCounter1;
|
|
case 2: return perfCounter2;
|
|
case 3: return perfCounter3;
|
|
case 4: return perfCounter4;
|
|
case 5: return perfCounter5;
|
|
case 6: return perfCounter6;
|
|
case 7: return perfCounter7;
|
|
case 8: return perfCounter8;
|
|
case 9: return perfCounter9;
|
|
case 10: return perfCounter10;
|
|
case 11: return perfCounter11;
|
|
case 12: return perfCounter12;
|
|
case 13: return perfCounter13;
|
|
case 14: return perfCounter14;
|
|
case 15: return perfCounter15;
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
[AccessedByRuntime("output to header : defined in halkd.cpp")]
|
|
[NoHeapAllocation]
|
|
public static bool WritePerfCounter(uint which, ulong value)
|
|
{
|
|
switch (which) {
|
|
case 0: perfCounter0 = value; return true;
|
|
case 1: perfCounter1 = value; return true;
|
|
case 2: perfCounter2 = value; return true;
|
|
case 3: perfCounter3 = value; return true;
|
|
case 4: perfCounter4 = value; return true;
|
|
case 5: perfCounter5 = value; return true;
|
|
case 6: perfCounter6 = value; return true;
|
|
case 7: perfCounter7 = value; return true;
|
|
case 8: perfCounter8 = value; return true;
|
|
case 9: perfCounter9 = value; return true;
|
|
case 10: perfCounter10 = value; return true;
|
|
case 11: perfCounter11 = value; return true;
|
|
case 12: perfCounter12 = value; return true;
|
|
case 13: perfCounter13 = value; return true;
|
|
case 14: perfCounter14 = value; return true;
|
|
case 15: perfCounter15 = value; return true;
|
|
default: return false;
|
|
}
|
|
}
|
|
|
|
[AccessedByRuntime("output to header : defined in halkd.cpp")]
|
|
[NoHeapAllocation]
|
|
public static bool AddToPerfCounter(uint which, ulong value)
|
|
{
|
|
switch (which) {
|
|
case 0: Interlocked.Add(ref perfCounter0, value); return true;
|
|
case 1: Interlocked.Add(ref perfCounter1, value); return true;
|
|
case 2: Interlocked.Add(ref perfCounter2, value); return true;
|
|
case 3: Interlocked.Add(ref perfCounter3, value); return true;
|
|
case 4: Interlocked.Add(ref perfCounter4, value); return true;
|
|
case 5: Interlocked.Add(ref perfCounter5, value); return true;
|
|
case 6: Interlocked.Add(ref perfCounter6, value); return true;
|
|
case 7: Interlocked.Add(ref perfCounter7, value); return true;
|
|
case 8: Interlocked.Add(ref perfCounter8, value); return true;
|
|
case 9: Interlocked.Add(ref perfCounter9, value); return true;
|
|
case 10: Interlocked.Add(ref perfCounter10, value); return true;
|
|
case 11: Interlocked.Add(ref perfCounter11, value); return true;
|
|
case 12: Interlocked.Add(ref perfCounter12, value); return true;
|
|
case 13: Interlocked.Add(ref perfCounter13, value); return true;
|
|
case 14: Interlocked.Add(ref perfCounter14, value); return true;
|
|
case 15: Interlocked.Add(ref perfCounter15, value); return true;
|
|
default: return false;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|