// ---------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // ---------------------------------------------------------------------------- //////////////////////////////////////////////////////////// // // File: MpSyscallBuilder.cs // // using System; using System.Collections; using System.IO; public class MpSyscallBuilder { public class AbiDef { public AbiDef() {} public int abiNum; // this number if important public string decl; public string longReturnType; public string shortReturnType; public string longMethodName; public string longClassName; public string namespaceName; public string shortClassName; public string shortMethodName; public string shortMethodNameWithG; public string [] longParamArray; public string [] shortParamArray; } const string s4 = " "; const string s8 = s4 + s4; const string s12 = s8 + s4; const string s16 = s12 + s4; static Hashtable globalClassTable = new Hashtable(); static Hashtable structTable = new Hashtable(); static Hashtable paramTable = new Hashtable(); static Hashtable linkStackTable = new Hashtable(); static Hashtable namespaceTable = new Hashtable(); static Hashtable typeConverter = new Hashtable(); // we allow 1000 abi defs const int MAX_ABI_DEF = 1000; static AbiDef [] sequentialAbiDef = new AbiDef [MAX_ABI_DEF]; static int curAbiNum = -1; static int lineNumber = 0; static int printCount = 0; static bool genSingStubV1Def = false; static bool genApAbiStub = false; static bool genBspAbiStub = false; static bool genMpSyscallsHeader = false; static bool genMpSyscallsImpl = false; static void AddType(string t) { if (t.StartsWith("struct ")) { int end = t.IndexOf(" ", 7); if (end == -1) { end = t.Length; } string structName = t.Substring(7, end - 7); //if (!structTable.ContainsKey(structName)) { //Console.WriteLine("// Adding " + structName); //} if (end < t.Length) { structTable[structName] = ""; } else { int ssize; if (structName.EndsWith("Handle")) { ssize = 4; } else { if (!paramTable.ContainsKey("struct " + structName)) { throw new Exception("unknown struct type: " + t); } ssize = (int) paramTable["struct " + structName]; } structTable[structName] = "char data[" + ssize + "];"; } } } static void AddTypeToStructTable(string t) { if (t.StartsWith("struct ")) { int end = t.IndexOf(" ", 7); if (end == -1) { end = t.Length; } string structName = t.Substring(7, end - 7); //if (!structTable.ContainsKey(structName)) { //Console.WriteLine("// Adding " + structName); //} if (end < t.Length) { structTable[structName] = ""; } else { int ssize; if (structName.EndsWith("Handle")) { ssize = 4; } else { if (!paramTable.ContainsKey("struct " + structName)) { throw new Exception("unknown struct type: " + t); } ssize = (int) paramTable["struct " + structName]; } structTable[structName] = "char data[" + ssize + "];"; } } } static int GetTypeSize(string type) { int size; if (type.EndsWith("*") || type.EndsWith("Handle")) { size = 4; } else { if (!paramTable.ContainsKey(type)) { throw new Exception ("unknown parameter type: " + type); } size = (int) paramTable[type]; } return size; } //////////////////////////////////////////////////////////////// // public static void PrintNamespaceTable() { AbiDef abiDef; Hashtable nsClassTable, methodTable; printCount = 0; Console.WriteLine("\n"); Console.WriteLine("/////////////////////////////////////"); Console.WriteLine("//"); Console.WriteLine("// This is the namespace hashtable : "); Console.WriteLine("//"); Console.WriteLine("/////////////////////////////////////\n"); foreach (string namespaceName in namespaceTable.Keys) { Console.WriteLine("\n" + namespaceName); Console.WriteLine("###################################################"); nsClassTable = (Hashtable)namespaceTable[namespaceName]; foreach (string className in nsClassTable.Keys) { Console.WriteLine("\n" + " " + className); Console.WriteLine(" ================================="); methodTable = (Hashtable)nsClassTable[className]; foreach (string decl in methodTable.Keys) { abiDef = (AbiDef)methodTable[decl]; PrintAbiDef(abiDef, " "); } } } } //////////////////////////////////////////////////////////////// // Print Abi Def public static void PrintAbiDef(AbiDef ad, string pre) { Console.WriteLine(pre + "\n[" + printCount++ + "]"); Console.WriteLine(pre + ad.decl); Console.WriteLine(pre + "---------------------------------------------------"); Console.WriteLine(pre + " ABI number : <{0,3}>", ad.abiNum); Console.WriteLine(pre + " longReturnType : <" + ad.longReturnType + ">"); Console.WriteLine(pre + " shortReturnType : <" + ad.shortReturnType + ">" + " sz: " + GetTypeSize(ad.longReturnType)); Console.WriteLine(pre + " longMethodName : <" + ad.longMethodName + ">"); Console.WriteLine(pre + " longClassName : <" + ad.longClassName + ">"); Console.WriteLine(pre + " namespaceName : <" + ad.namespaceName + ">"); Console.WriteLine(pre + " shortClassName : <" + ad.shortClassName + ">"); Console.WriteLine(pre + " shortMethodName : <" + ad.shortMethodName + ">"); Console.WriteLine(pre + " shortMethodName2: <" + ad.shortMethodNameWithG + ">"); // test param for (int v = 0; v < ad.longParamArray.Length; v++) { string p = " "; if (ad.longParamArray[v] != "") { Console.WriteLine(pre + " param " + v + " : "); Console.WriteLine(pre + p + "longParam : <" + ad.longParamArray[v] + ">"); Console.WriteLine(pre + p + "shortParam : <" + ad.shortParamArray[v] + ">" + " sz: " + GetTypeSize(ad.longParamArray[v])); } } Console.WriteLine(); } //////////////////////////////////////////////////////////////// // Option : genSingStubV1Def // Input file : $(OBJ)/Singularity.V1.def // Output file : $(OBJ)/SingularityStub.V1.def // Note : This generates SingularityStub.V1.def which is // basically Singularity.V1.def plus the stubs // definition // Example : Given a line like this // ?g_Abi@Struct_Micr_Sing_V1_Services_ProcessService@@SIHH@Z // It adds the new stub function in the new stub struct: // ?g_StubAbi@Struct_Micr_Sing_V1_Services_ProcessService@@SIHH@Z public static void GenerateSingularityStubV1Def() { // String Indexes: // ?g_Break@Struct_Microsoft_Singularity_V1_Services_DebugService@@SIXXZ // a b c d // method namespaceName structName suffix int a, b, c, d, tmp; string methodName = ""; string structName = ""; string namespaceName = ""; string suffix = ""; lineNumber = 0; while (true) { // read line string s = Console.ReadLine(); lineNumber++; if (s == null) { break; } // print the line first Console.WriteLine(s); // is this abi definition a = s.IndexOf('?'); if (a == -1) { continue; } // At this point, we currently does not support some files // For example: EndpointCore.cs is not located in // Singularity/V1/Services/EndpointCore.cs // instead in Singularity/Channels/EndpointCore // So we're not creating the stubs for here for now. // Need to think some solutions later. if (s.IndexOf("_EndpointCore@") != -1) { continue; } b = s.IndexOf('@'); d = s.IndexOf('@', b+1); tmp = b; c = b; while (true) { tmp = s.IndexOf('_', tmp+1); if (tmp == -1 || tmp > d) { break; } c = tmp; } methodName = s.Substring(a, b-a); // include '?' namespaceName = s.Substring(b+1, c-(b+1)); structName = s.Substring(c+1, d-(c+1)); suffix = s.Substring(d, s.Length-d); // add "Stub" to methodName if (methodName.IndexOf("?g_") != -1) { methodName = methodName.Replace("?g_", "?g_Stub"); } else if (methodName.IndexOf("?m_") != -1) { methodName = methodName.Replace("?m_", "?m_Stub"); } // add "Stub" to structName // Nope not necessary .... // structName = "Stub" + structName; // Console.WriteLine(" namespace : <" + namespaceName + ">"); // Console.WriteLine(" struct : <" + structName + ">"); // Console.WriteLine(" method : <" + methodName + ">"); // Console.WriteLine(" suffix : <" + suffix + ">"); Console.WriteLine(" " + methodName + "@" + namespaceName + "_" + structName + suffix); } } //////////////////////////////////////////////////////////////// // Array string for storing parameter // We allow maximum of 20 parameters. If not enough, change // the constant. public static string [] GetParamArray() { string [] paramArray = new string [20]; for (int i = 0; i < paramArray.Length; i++) { paramArray[i] = ""; } return paramArray; } //////////////////////////////////////////////////////////////// // The function separates a long struct name into two parts // divided by the last underscore mark "_" // Example: // longName : struct Struct_Micr_Sing_V1_Services_SharedHeapService_Allocation * // firstPart : struct Struct_Micr_Sing_V1_Services_SharedHeapService_ // secondPart: Allocation * // WARNING: // However we must careful with types that have "_". So we need to check if it // is a struct or not, if not, we just set secondPart = longName public static void SeparateLongStructName(string longName, out string firstPart, out string secondPart) { int tmp, i=0; if (longName.IndexOf("_") == -1) { firstPart = "ERROR IGNORE"; secondPart = longName; return; } // this is not a struct if (longName.IndexOf("Struct_") == -1) { firstPart = ""; secondPart = longName; return; } tmp = 0; while (true) { tmp = longName.IndexOf('_', tmp+1); if (tmp == -1) { break; } i = tmp; } firstPart = longName.Substring(0, i); secondPart = longName.Substring(i+1, longName.Length-(i+1)); } public static void SeparateNamespaceAndClass(string longName, out string nsName, out string className) { int tmp = 0; int i = 0; tmp = 0; while (true) { tmp = longName.IndexOf('.', tmp+1); if (tmp == -1) { break; } i = tmp; } nsName = longName.Substring(0, i); className = longName.Substring(i+1, longName.Length-(i+1)); } // increase abi number number static void IncrementAbiNumber(string s) { if (s.IndexOf("?g_") != -1 || s.IndexOf("?m_") != -1) { curAbiNum++; } } //////////////////////////////////////////////////////////////// // Option : genApAbiStub // Input file : $(OBJ)/SingularityStub.V1.dumpbin // Output file : StubXXX.cs (Find all Stub*.cs files // Note : This create the Stub files which contains the stub functions // that will perform the marshaling and IPI // Example: // // public static void GenerateApAbiStub() { printCount = 0; string s; AbiDef abiDef; while (true) { s = Console.ReadLine(); lineNumber++; // end of file if (s == null) { break; } // We only create stub files and functions for abi definition that has // g_Stub or m_Stub if (s.IndexOf("?g_Stub") == -1 && s.IndexOf("?m_Stub") == -1) { continue; } IncrementAbiNumber(s); abiDef = new AbiDef(); ParseLineToAbiDef(s, abiDef); // PrintAbiDef(abiDef, ""); // Now we add abiDef to hashtable AddAbiDefToHashTable(abiDef); } // test PrintNamespaceTable(); BeginCreatingApAbiStubFromNamespaceTable(); } //////////////////////////////////////////////////////////////// // // namespaceTable[Struct_Microsoft_Singularity_V1_Services] --> nsClassTable // nsClassTable[ProcessService] --> methodTable // methodTable[decl] -> abiDef // public static void AddAbiDefToHashTable(AbiDef abiDef) { // Hashtable nsClassTable = (Hashtable)namespaceTable[abiDef.namespaceName]; if (nsClassTable == null) { nsClassTable = new Hashtable(); namespaceTable[abiDef.namespaceName] = nsClassTable; } Hashtable methodTable = (Hashtable)nsClassTable[abiDef.shortClassName]; if (methodTable == null) { methodTable = new Hashtable(); nsClassTable[abiDef.shortClassName] = methodTable; } methodTable[abiDef.decl] = abiDef; } //////////////////////////////////////////////////////////////// // // We need to create the fullFileName = dirName + fileName // public static void BeginCreatingApAbiStubFromNamespaceTable() { AbiDef abiDef; Hashtable nsClassTable, methodTable; string abiFileName, stubFileName, dirName, fileName; foreach (string namespaceName in namespaceTable.Keys) { nsClassTable = (Hashtable)namespaceTable[namespaceName]; dirName = namespaceName.Replace("Struct_Microsoft_", ""); dirName = dirName.Replace("_","/"); foreach (string className in nsClassTable.Keys) { methodTable = (Hashtable)nsClassTable[className]; fileName = className + ".cs"; abiFileName = dirName + "/" + fileName; // Now we get the abiFileName at this point. e.g. // Singularity/V1/Services/ProcessService.cs // Next we want to copy the file to // Singularity/V1/Services/StubProcessService.cs with // exception the last bracket "}" because we want to // add the stub functions to the file stubFileName = GetStubFileName(abiFileName); Console.WriteLine("Copy " + abiFileName); Console.WriteLine(" " + stubFileName); if (File.Exists(stubFileName)) { File.Delete(stubFileName); } FileStream fsOutput = new FileStream(stubFileName, FileMode.Create, FileAccess.Write); StreamWriter stubOut = new StreamWriter(fsOutput); FileStream fsInput = new FileStream(abiFileName, FileMode.Open, FileAccess.Read); StreamReader abiIn = new StreamReader(fsInput); CopyAbiFileToStubFile(abiIn, stubOut, abiFileName, stubFileName, className); foreach (string decl in methodTable.Keys) { abiDef = (AbiDef)methodTable[decl]; WriteApAbiStubClassMethod(stubOut, abiDef); } WriteApAbiStubClassFooter(stubOut); abiIn.Close(); stubOut.Close(); } } } // Given abiFileName a/b/c/d/ProcessService.cs // this function returns a/b/c/d/StubProcessService.cs public static string GetStubFileName(string abiFileName) { string dirName, fileName; int tmp = 0; int i = 0; tmp = 0; while (true) { tmp = abiFileName.IndexOf('/', tmp+1); if (tmp == -1) { break; } i = tmp; } dirName = abiFileName.Substring(0, i); fileName = abiFileName.Substring(i+1, abiFileName.Length-(i+1)); return (dirName + "/Stub" + fileName); } // Copy abi file to stub file, except the last bracket // This is a copy line per line ... maybe in future we should // write a quick script? public static void CopyAbiFileToStubFile(StreamReader abiIn, StreamWriter stubOut, string abiFileName, string stubFileName, string className) { stubOut.WriteLine("///////////////////////////////////////////////////////"); stubOut.WriteLine("// "); stubOut.WriteLine("// THIS IS AUTOMATICALLY GENERATED FILE, DO NOT MODIFY "); stubOut.WriteLine("// "); stubOut.WriteLine("// Generated by: Windows/MpSyscall/MpSyscallBuilder.exe"); stubOut.WriteLine("// "); stubOut.WriteLine("// Abi File " + abiFileName); stubOut.WriteLine("// Stub File " + stubFileName); stubOut.WriteLine("// "); stubOut.WriteLine(""); bool isClassDeclared = false; string s = abiIn.ReadLine(); while (s != null) { if (s.IndexOf("public struct " + className) != -1) { isClassDeclared = true; } // find the last bracket after class declaration if (isClassDeclared && s.IndexOf(" }") == 0) { stubOut.WriteLine(""); break; } stubOut.WriteLine(s); s = abiIn.ReadLine(); } } public static void WriteApAbiStubClassFooter(StreamWriter sw) { sw.WriteLine(" }"); sw.WriteLine("}"); } public static void WriteApAbiStubClassMethod(StreamWriter sw, AbiDef ad) { string csType; sw.WriteLine(s8 + "[ExternalEntryPoint]"); // Right now we just treat all stub functions as non CLS compliant // For 100% correctness, this is not true sw.WriteLine(s8 + "[CLSCompliant(false)]"); // function declare sw.Write(s8 + "public static unsafe " + GetCsType(ad.shortReturnType, ad.longReturnType) + " " + ad.shortMethodName + "("); for (int i = 0; i < ad.shortParamArray.Length; i++) { if (ad.shortParamArray[i] != "") { if (ad.shortParamArray[i] != "void") { csType = GetCsType(ad.shortParamArray[i], ad.longParamArray[i]); if (i == 0) { sw.Write(csType + " p" + i) ; } else { sw.Write(", " + csType + " p" + i); } } } } sw.WriteLine(")"); sw.WriteLine(s8 + "{"); // write function body now bool allApAbiStub = true; if (allApAbiStub) { WriteApAbiStubClassMethodBodyGeneric(sw, ad); } else if (ad.shortMethodName == "StubHelloProcessABI" || ad.shortMethodName == "StubTestAbiCallOne" || ad.shortMethodName == "StubTestAbiCallTwo" || ad.shortMethodName == "StubTestAbiCallThree" || false) { WriteApAbiStubClassMethodBodyGeneric(sw, ad); // WriteApAbiStubClassMethodBodySample(sw, ad); } else { WriteApAbiStubClassMethodBodyBlank(sw, ad); } sw.WriteLine(s8 + "}"); sw.WriteLine(); } public static string stubHelloProcessABICode = "\n int ap = Processor.GetCurrentProcessorId();" + "\n int bsp = 0;" + "\n" + "\n DebugStub.WriteLine" + "\n (\"\\n\\nHSG: ** cpu.{0} StubHelloProcessABI({1})\"," + "\n __arglist(ap, p0));" + "\n DebugStub.WriteLine(\"HSG: ** -------------------------\");" + "\n" + "\n bool iflag = Processor.DisableInterrupts();" + "\n" + "\n MpExecution.AbiCall abiCall = new MpExecution.AbiCall();" + "\n" + "\n // 1) set up all the parameters" + "\n abiCall.argVal = p0;" + "\n" + "\n // prepare IPI" + "\n DebugStub.Print" + "\n (\"HSG: ** cpu.{0} PutAbiCall(cpu.{1}, arg.{2}) --> \"," + "\n __arglist(ap, bsp, abiCall.argVal));" + "\n" + "\n // 2) register the abiCall," + "\n // after this, we get the position" + "\n int pos = MpExecution.PutAbiCall(bsp, abiCall);" + "\n" + "\n DebugStub.WriteLine(\"pos.{0}\", __arglist(pos));" + "\n" + "\n DebugStub.WriteLine" + "\n (\"HSG: ** cpu.{0} SendAbiCall(cpu.{1}, cpu.{2})\"," + "\n __arglist(ap, ap, bsp));" + "\n" + "\n // 3) send" + "\n MpExecution.SendAbiCall(ap, bsp);" + "\n" + "\n DebugStub.WriteLine" + "\n (\"HSG: ** cpu.{0} WaitAbiCall(cpu.{1}, pos.{2}) ... zzz \", " + "\n __arglist(ap, bsp, pos));" + "\n" + "\n // 4) spin until done" + "\n MpExecution.WaitAbiCall(bsp, pos, out abiCall);" + "\n" + "\n // 5) we have the return value" + "\n int retval = abiCall.retVal;" + "\n" + "\n DebugStub.WriteLine" + "\n (\"HSG: ** cpu.{0} is waken up and receives retval.{1}\"," + "\n __arglist(ap, retval));" + "\n" + "\n DebugStub.WriteLine" + "\n (\"HSG: ** cpu.{0} ReleaseAbiCall(cpu.{1}, pos.{2})\"," + "\n __arglist(ap, bsp, pos));" + "\n" + "\n // 6) release abiCall" + "\n MpExecution.ReleaseAbiCall(bsp, pos);" + "\n" + "\n Processor.RestoreInterrupts(iflag);" + "\n" + "\n return retval;" + "\n"; public static void WriteApAbiStubClassMethodBodySample(StreamWriter sw, AbiDef ad) { string type = GetCsType(ad.shortReturnType, ad.longReturnType); sw.WriteLine(s12 + "DebugStub.WriteLine(\"HSG: ** In " + ad.shortMethodName + "{0}\", __arglist(p0));"); sw.WriteLine(stubHelloProcessABICode); } public static void WriteApAbiStubClassMethodBodyGeneric(StreamWriter sw, AbiDef ad) { int curOffset, size; // some variables, ap, bsp, iflag, retval sw.WriteLine(s12 + "DebugStub.WriteLine(\"HSG: ** " + ad.shortMethodName + "()\");"); sw.WriteLine(s12 + "int ap = Processor.GetCurrentProcessorId();"); sw.WriteLine(s12 + "int bsp = 0;"); sw.WriteLine(s12 + "bool iflag;"); sw.WriteLine(s12 + ""); // declare return value if (ad.shortReturnType != "void") { sw.WriteLine(s12 + GetCsType(ad.shortReturnType, ad.longReturnType) + " retval;"); sw.WriteLine(s12 + ""); } // get the mpCall sw.WriteLine(s12 + "iflag = Processor.DisableInterrupts();"); sw.WriteLine(s12 + "MpExecution.MpCall mpCall = MpExecution.ReserveMpCall(bsp);"); sw.WriteLine(s12 + "Processor.RestoreInterrupts(iflag);"); sw.WriteLine(s12 + ""); sw.WriteLine(s12 + "if (mpCall == null) {"); sw.WriteLine(s12 + " DebugStub.WriteLine(\"MpCall buffer full\");"); sw.WriteLine(s12 + " DebugStub.Break();"); sw.WriteLine(s12 + "}"); sw.WriteLine(s12 + ""); // set mpCall number sw.WriteLine(s12 + "mpCall.abiNum = " + ad.abiNum + "; // abi number"); sw.WriteLine(s12 + ""); // start marshal arguments sw.WriteLine(s12 + "// future: need check not to overrun buffer"); sw.WriteLine(s12 + "// marshall arguments"); sw.WriteLine(s12 + "fixed (byte *baseArg = & mpCall.argBuffer[0] ) {"); curOffset = 0; for (int v = 0; v < ad.shortParamArray.Length; v++) { if (ad.shortParamArray[v] != "" && ad.shortParamArray[v] != "void") { size = GetTypeSize(ad.longParamArray[v]); sw.WriteLine(s12 + " Buffer.MoveMemory(baseArg+" + curOffset + " , (byte*) & p" + v + " , " + size + ");"); curOffset += size; } } sw.WriteLine(s12 + "}"); sw.WriteLine(s12 + ""); // send mp call and wait sw.WriteLine(s12 + "iflag = Processor.DisableInterrupts();"); sw.WriteLine(s12 + "MpExecution.SendMpCall(ap, bsp);"); sw.WriteLine(s12 + "Processor.RestoreInterrupts(iflag);"); sw.WriteLine(s12 + ""); sw.WriteLine(s12 + "MpExecution.WaitMpCall(bsp, mpCall.position);"); sw.WriteLine(s12 + ""); // return value is available if (ad.shortReturnType != "void") { sw.WriteLine(s12 + "// get return value"); sw.WriteLine(s12 + "fixed (byte *baseRet = & mpCall.retBuffer[0] ) {"); sw.WriteLine(s12 + " Buffer.MoveMemory( (byte*) & retval , baseRet, " + GetTypeSize(ad.longReturnType) + ");"); sw.WriteLine(s12 + "} "); sw.WriteLine(s12 + ""); } // copy back out parameter sw.WriteLine(s12 + "// also in case we have 'out param', copy back parameters"); sw.WriteLine(s12 + "fixed (byte *baseArg = & mpCall.argBuffer[0] ) {"); curOffset = 0; for (int v = 0; v < ad.shortParamArray.Length; v++) { if (ad.shortParamArray[v] != "" && ad.shortParamArray[v] != "void") { size = GetTypeSize(ad.longParamArray[v]); sw.WriteLine(s12 + " Buffer.MoveMemory((byte*) & p" + v + " , baseArg+" + curOffset + " , " + size + ");"); curOffset += size; } } sw.WriteLine(s12 + "}"); sw.WriteLine(s12 + ""); // release and return value sw.WriteLine(s12 + "iflag = Processor.DisableInterrupts();"); sw.WriteLine(s12 + "MpExecution.ReleaseMpCall(bsp, mpCall.position);"); sw.WriteLine(s12 + "Processor.RestoreInterrupts(iflag);"); sw.WriteLine(s12 + ""); if (ad.shortReturnType != "void") { sw.WriteLine(s12 + "return retval;"); } else { sw.WriteLine(s12 + "return;"); } } public static void WriteApAbiStubClassMethodBodyBlank(StreamWriter sw, AbiDef ad) { string type = GetCsType(ad.shortReturnType, ad.longReturnType); // print debug sw.WriteLine(s12 + "DebugStub.WriteLine(\"HSG: ** In " + ad.shortMethodName + "\");"); // if it's a void, do nothing if (type == "void") { sw.WriteLine(""); } // it's a pointer else if (type.IndexOf("*") != -1) { // sw.WriteLine(s12 + GetCsType(ad.shortReturnType, ad.longReturnType) + " x;"); sw.WriteLine(s12 + "return null;"); } // it's a class else if (ad.shortReturnType != ad.longReturnType) { sw.WriteLine(s12 + type + " x = new " + type + "();"); sw.WriteLine(s12 + "return x;"); } // else else if (type.IndexOf("bool") != -1) { sw.WriteLine(s12 + "return false;"); } else { sw.WriteLine(s12 + "return (" + GetCsType(ad.shortReturnType, ad.longReturnType) + ") 0;"); } } // Convert C/C++ type into C# type // For example convert wchar_t to char // This function consults the typeConverter hash table public static string GetCsType(string cType, string longVersionType) { // first before we convert we check some ambiguities string unambiguousType = ""; CheckAmbiguities(cType, longVersionType, out unambiguousType); if (unambiguousType != "") { return unambiguousType; } // Other than that, we will convert the C/C++ type into // C# type. if (typeConverter[cType] == null) { return cType; } else { return (string)typeConverter[cType]; } } // This checks ambiguity for BspAbiStub // Here is the ambiguity error: // Singularity\BspAbiStub.cs(2202,13): error CS0104: // 'ProcessState' is an ambiguous reference // Singularity\BspAbiStub.cs(2249,13): error CS0104: // 'ThreadState' is an ambiguous reference public static string GetCsTypeForBspAbiStub(string cType, string longVersionType) { string tmp = GetCsType(cType, longVersionType); if (tmp == "ThreadState") { return "Microsoft.Singularity.V1.Threads.ThreadState"; } else if (tmp == "ProcessState") { return "Microsoft.Singularity.V1.Processes.ProcessState"; } else { return tmp; } } // This is all hacks to resolve "ambiguity" public static void CheckAmbiguities(string cType, string longVersionType, out string unambiguousType) { // Now this is a hack .. for now .. The problem is when we // get the short version of the type we always get the last // word after the last "_" For example in: // Struct_Microsoft_Singularity_V1_Services_SharedHeapService_Allocation // We set the shortType to be "Allocation". But that is not // correct because the correct type is actually // "SharedHeapService.Allocation" if (cType.IndexOf("Allocation") == 0) { string str1, str2; SeparateLongStructName(longVersionType, out str1, out str2); SeparateLongStructName(str1, out str1, out str2); unambiguousType = (str2 + "." + cType); return; } unambiguousType = ""; return; } //////////////////////////////////////////////////////////////// // public static void ParseLineToAbiDef(string s, AbiDef abiDef) { abiDef.abiNum = curAbiNum; ParseLine(s, out abiDef.decl, out abiDef.longReturnType, out abiDef.shortReturnType, out abiDef.longMethodName, out abiDef.longClassName, out abiDef.namespaceName, out abiDef.shortClassName, out abiDef.shortMethodName, out abiDef.shortMethodNameWithG, out abiDef.longParamArray, out abiDef.shortParamArray); } public static void ParseLine(string s, out string decl, out string longReturnType, out string shortReturnType, out string longMethodName, out string longClassName, out string namespaceName, out string shortClassName, out string shortMethodName, out string shortMethodNameWithG, out string [] longParamArray, out string [] shortParamArray) { int i, j, k, pnum; string tmpStr, param; i = s.IndexOf("static"); if (i == -1) { throw new Exception("line " + lineNumber + " not static"); } i += 7; // the whole declaration // e.g. "int __fastcall // Struct_Microsoft_Singularity_V1_Services_ProcessService // ::g_HelloProcessABI(int)" j = s.IndexOf(')', i); decl = s.Substring(i, j + 1 - i); // right now we're just working with "decl" i = decl.IndexOf("__fastcall"); if (i == -1) { throw new Exception("line " + lineNumber + " not __fastcall"); } // Get the return type longReturnType = decl.Substring(0, i-1); // Add long return type to structTable AddTypeToStructTable(longReturnType); // Check if longReturnType is struct type, if so we make // the simple type // Example: // longReturnType : struct Struct_Micr_Sing_V1_Services_ShrHpServ_Allocation * // shortReturnType: Allocation * SeparateLongStructName(longReturnType, out tmpStr, out shortReturnType); // now shortReturnType (or any return type) could contain "Stub" // The reason for this is when we generate Singularity.V1.lib from // Singularity.V1.def, a method M in class StubC could have return type StubC. // But that's not what we want, we want a return type of C instead of StubC // Here is for example: // StubSystemType::StubRootSystemType returns SubSystemType // It should actually return SystemType // The same thing applies for "param" if (shortReturnType.IndexOf("Stub") == 0) { shortReturnType = shortReturnType.Substring(4,shortReturnType.Length-4); } // Right now the string left at index i is: // e.g. " Struct_Microsoft_Singularity_V1_Services_ProcessService // ::g_HelloProcessABI(int)" // Get the long class name i = decl.IndexOf(' ', i) + 1; j = decl.IndexOf("::", i); k = decl.IndexOf("(", j); longClassName = decl.Substring(i, j - i); // we have the long class name, add this to the globalClassTable globalClassTable[longClassName] = true; longMethodName = decl.Substring(i, k - i); shortMethodNameWithG = decl.Substring(j + 2, k - (j + 2)); if (shortMethodNameWithG.IndexOf("g_") != -1) { shortMethodName = shortMethodNameWithG.Replace("g_",""); } else if (shortMethodNameWithG.IndexOf("m_") != -1) { shortMethodName = shortMethodNameWithG.Replace("m_",""); } else { throw new Exception("line " + lineNumber + " method not have g_/m_"); } // Now given the longClassName we want to get the // namespaceName and shortClassName // Example: // longClassName : Struct_Microsoft_Singularity_V1_Services_StubProcessService // namespaceName : Struct_Microsoft_Singularity_V1_Service // shortClassName : StubProcessService SeparateLongStructName(longClassName, out namespaceName, out shortClassName); // Now we're starting to get the arguments longParamArray = GetParamArray(); shortParamArray = GetParamArray(); i = decl.IndexOf('(') + 1; pnum = 0; while (decl[i] != ')') { j = decl.IndexOf(',', i); if (j == -1) { j = decl.IndexOf(')', i); param = decl.Substring(i, j - i); longParamArray[pnum] = param; pnum++; break; } param = decl.Substring(i, j - i); longParamArray[pnum] = param; pnum++; i = j + 1; } // Add long param array to struct table for (int v = 0; v < longParamArray.Length; v++) { if (longParamArray[v] != "") { AddTypeToStructTable(longParamArray[v]); } } // The params are ready we make shorter param now for (int v = 0; v < longParamArray.Length; v++) { if (longParamArray[v] != "") { SeparateLongStructName(longParamArray[v], out tmpStr, out shortParamArray[v]); // fix short param (the same case as in shortReturnType above) // this might not be necessary anymore // //if (shortParamArray[v].IndexOf("Stub") == 0) { // shortParamArray[v] = shortParamArray[v].Substring(4,shortParamArray[v].Length-4); // } } } } //////////////////////////////////////////////////////////////// // Option : // Input file : $(OBJ)/SingularityStub.V1.dumpbin // Output file : // Note : // // Example: // // public static void GenerateMpSyscallsHeader() { printCount = 0; string s; AbiDef abiDef; while (true) { s = Console.ReadLine(); lineNumber++; // end of file if (s == null) { break; } // g_ or m_ if (s.IndexOf("?g_") == -1 && s.IndexOf("?m_") == -1) { continue; } abiDef = new AbiDef(); ParseLineToAbiDef(s, abiDef); // PrintAbiDef(abiDef, ""); // Now we add abiDef to hashtable AddAbiDefToHashTable(abiDef); } // test // PrintNamespaceTable(); BeginCreatingMpSyscallsHeader(); } public static void BeginCreatingMpSyscallsHeader() { // go through all the namespace AbiDef ad; Hashtable nsClassTable, methodTable; // header Console.WriteLine("////////////////////////////////////////////////////////////"); Console.WriteLine("// Automatically generated files by MpSyscallsBuilder.exe"); Console.WriteLine("// "); // First of all create external undefined structs foreach (string s in structTable.Keys) { if (!globalClassTable.ContainsKey(s)) { Console.WriteLine("struct " + s + " {" + structTable[s] + "};"); } } Console.WriteLine(); // Next, create struct declarations foreach (string namespaceName in namespaceTable.Keys) { nsClassTable = (Hashtable)namespaceTable[namespaceName]; foreach (string className in nsClassTable.Keys) { Console.WriteLine("struct " + namespaceName + "_" + className); Console.WriteLine("{"); methodTable = (Hashtable)nsClassTable[className]; foreach (string decl in methodTable.Keys) { ad = (AbiDef)methodTable[decl]; // A stub, export if (ad.shortMethodName.IndexOf("Stub") == 0) { Console.Write(" static " + ad.longReturnType + " " + ad.shortMethodNameWithG + "("); } else { Console.Write(" __declspec(dllexport) static " + ad.longReturnType + " __fastcall " + ad.shortMethodNameWithG + "("); } // parameters for (int v = 0; v < ad.longParamArray.Length; v++) { if (ad.longParamArray[v] != "") { if (ad.longParamArray[v] != "void") { if (v == 0) { Console.Write(ad.longParamArray[v]) ; } else { Console.Write(", " + ad.longParamArray[v]); } } } } Console.WriteLine(");"); } Console.WriteLine("};"); Console.WriteLine(""); } } } //////////////////////////////////////////////////////////////// // Option : // Input file : $(OBJ)/SingularityStub.V1.dumpbin // Output file : // Note : // // Example: // // public static void GenerateMpSyscallsImpl() { printCount = 0; string s; AbiDef abiDef; while (true) { s = Console.ReadLine(); lineNumber++; // end of file if (s == null) { break; } // g_ or m_ if (s.IndexOf("?g_") == -1 && s.IndexOf("?m_") == -1) { continue; } abiDef = new AbiDef(); ParseLineToAbiDef(s, abiDef); // PrintAbiDef(abiDef, ""); // Now we add abiDef to hashtable AddAbiDefToHashTable(abiDef); } // test // PrintNamespaceTable(); BeginCreatingMpSyscallsImpl(); } // Whenever MpSyscalls.x86 has bigger .rdata area, the kernel is // crashing (e.g. got different kind of exceptions during boot) no matter // where we allocate MpSyscalls.x86 (either in 0x00500000 or 0x10500000) // So we're not generating all implementations. Right now we are just // generating GetUtcTime and HelloProcessABI // Here is an example of the crash: // This is fine: // add 00500000..00500400 pe .\obj\Prototype.ApicMP.Min.MarkSweep\MpSyscalls.x86 // add 00501000..00501200 .text .\obj\Prototype.ApicMP.Min.MarkSweep\MpSyscalls.x86 // add 00502000..00502c00 .rdata .\obj\Prototype.ApicMP.Min.MarkSweep\MpSyscalls.x86 // This causes a crash: // add 00500000..00500400 pe .\obj\Prototype.ApicMP.Min.MarkSweep\MpSyscalls.x86 // add 00501000..00501400 .text .\obj\Prototype.ApicMP.Min.MarkSweep\MpSyscalls.x86 // add 00502000..00504200 .rdata .\obj\Prototype.ApicMP.Min.MarkSweep\MpSyscalls.x86 public static bool DoesNotCauseKernelCrash(string namespaceName, string className, string methodName) { // to test more functions/class/namespace, just add the // corresponding conditions if (methodName.IndexOf("HelloProcessABI") != -1 || methodName.IndexOf("TestAbiCallOne") != -1 || methodName.IndexOf("TestAbiCallTwo") != -1 || methodName.IndexOf("TestAbiCallThree") != -1 || // methodName.IndexOf("GetUtcTime") != -1 || false) { return true; } return false; } public static void BeginCreatingMpSyscallsImpl() { // go through all the namespace AbiDef ad; Hashtable nsClassTable, methodTable; // header Console.WriteLine("////////////////////////////////////////////////////////////"); Console.WriteLine("// Automatically generated files by MpSyscallsBuilder.exe"); Console.WriteLine("// "); Console.WriteLine("#include \"MpSyscalls.h\""); Console.WriteLine(""); Console.WriteLine("int entry() { return 0; }"); Console.WriteLine(""); // Next, create struct declarations foreach (string namespaceName in namespaceTable.Keys) { nsClassTable = (Hashtable)namespaceTable[namespaceName]; foreach (string className in nsClassTable.Keys) { methodTable = (Hashtable)nsClassTable[className]; foreach (string decl in methodTable.Keys) { ad = (AbiDef)methodTable[decl]; // we only generate methods that have no "Stub" if (ad.shortMethodName.IndexOf("Stub") != 0) { WriteMpSyscallsImplMethod(ad); } } } } } public static void WriteMpSyscallsImplMethod(AbiDef ad) { string cm; int ptotal; // if cause kernel crash, we just add comment code cm = "// "; if (DoesNotCauseKernelCrash(ad.namespaceName, ad.shortClassName, ad.shortMethodName)) { cm = ""; } // function Console.Write(cm + "__declspec(dllexport) " + ad.longReturnType + " __fastcall " + ad.longClassName + "::" + ad.shortMethodNameWithG + "("); // parameters ptotal = 0; for (int v = 0; v < ad.longParamArray.Length; v++) { if (ad.longParamArray[v] != "") { if (ad.longParamArray[v] != "void") { if (v == 0) { Console.Write(ad.longParamArray[v] + " p" + v) ; } else { Console.Write(", " + ad.longParamArray[v] + " p" + v); } ptotal++; } } } Console.WriteLine(")"); Console.WriteLine(cm + "{"); // function body // We are not supporting EndpointCore right now .. if (ad.shortClassName.IndexOf("EndpointCore") != -1) { Console.WriteLine(cm + " __asm { int 3 }"); } else { WriteMpSyscallsImplMethodBody(cm, ad, ptotal); } Console.WriteLine(cm + "}"); Console.WriteLine(""); } public static void WriteMpSyscallsImplMethodBody(string cm, AbiDef ad, int ptotal) { Console.Write(cm + " "); if (ad.longReturnType != "void") { Console.Write("return "); } Console.Write(ad.longClassName + "::" + GetStubMethodName(ad.shortMethodNameWithG) + "("); for (int v = 0; v < ptotal; v++) { if (v != 0) { Console.Write(", "); } Console.Write("p" + v); } Console.WriteLine(");"); } // Given g_Method, or m_Method it returns g_StubMethod or m_StubMethod public static string GetStubMethodName(string methodNameWithG) { string tmp1, tmp2; int i; i = methodNameWithG.IndexOf("_"); tmp1 = methodNameWithG.Substring(0, i); tmp2 = methodNameWithG.Substring(i+1, methodNameWithG.Length-(i+1)); return (tmp1 + "_Stub" + tmp2); } //////////////////////////////////////////////////////////////// // Option : genBspAbiStub // Input file : $(OBJ)/SingularityStub.V1.dumpbin // Output file : Singularity\BspAbiStub.cs (Find all Stub*.cs files // Note : This create the Stub files which contains the stub functions // that will perform the marshaling and IPI // Example: // // public static void GenerateBspAbiStub() { printCount = 0; string s; AbiDef abiDef; while (true) { s = Console.ReadLine(); lineNumber++; // end of file if (s == null) { break; } // We only create stub files and functions for abi definition that has // g_Stub or m_Stub if (s.IndexOf("?g_Stub") == -1 && s.IndexOf("?m_Stub") == -1) { continue; } IncrementAbiNumber(s); abiDef = new AbiDef(); ParseLineToAbiDef(s, abiDef); // PrintAbiDef(abiDef, ""); InsertToSequentialAbiDef(abiDef); // Now we add abiDef to hashtable AddAbiDefToHashTable(abiDef); } BeginCreatingBspAbiStubFromNamespaceTable(); } public static void InsertToSequentialAbiDef(AbiDef abiDef) { sequentialAbiDef[curAbiNum] = abiDef; } public static void BeginCreatingBspAbiStubFromNamespaceTable() { WriteBspAbiStubFileHeader(); WriteBspAbiStubEntry(); WriteBspAbiStubMethods(); WriteBspAbiStubFileFooter(); } public static void WriteBspAbiStubFileHeader() { Console.WriteLine("///////////////////////////////////////////////////////"); Console.WriteLine("// "); Console.WriteLine("// THIS IS AUTOMATICALLY GENERATED FILE, DO NOT MODIFY "); Console.WriteLine("// "); Console.WriteLine("// Generated by: Windows/MpSyscall/MpSyscallBuilder.exe"); Console.WriteLine("// "); Console.WriteLine("// "); Console.WriteLine(""); Console.WriteLine("using System;"); Console.WriteLine("using System.Runtime.InteropServices;"); Console.WriteLine("using System.Runtime.CompilerServices;"); Console.WriteLine("using System.Threading;"); Console.WriteLine("using Microsoft.Singularity.Hal;"); Console.WriteLine("using Microsoft.Singularity.Io;"); Console.WriteLine("using Microsoft.Singularity.Memory;"); Console.WriteLine("using Microsoft.Singularity.Scheduling;"); Console.WriteLine("using Microsoft.Singularity.IX;"); Console.WriteLine("using Microsoft.Singularity.V1.Processes;"); Console.WriteLine("using Microsoft.Singularity.V1.Security;"); Console.WriteLine("using Microsoft.Singularity.V1.Services;"); Console.WriteLine("using Microsoft.Singularity.V1.Stress;"); Console.WriteLine("using Microsoft.Singularity.V1.Threads;"); Console.WriteLine("using Microsoft.Singularity.V1.Types;"); Console.WriteLine(""); Console.WriteLine("namespace Microsoft.Singularity"); Console.WriteLine("{"); Console.WriteLine(" [CLSCompliant(false)]"); Console.WriteLine(" public class BspAbiStub"); Console.WriteLine(" {"); } public static void WriteBspAbiStubFileFooter() { Console.WriteLine(" }"); Console.WriteLine("}"); } public static void WriteBspAbiStubEntry() { AbiDef ad; // Console.WriteLine(s8 + "[NoHeapAllocation]"); Console.WriteLine(s8 + "public static unsafe void ProcessMpCall(int cpu, MpExecution.MpCall mpCall)"); Console.WriteLine(s8 + "{"); Console.WriteLine(s12 + "switch (mpCall.abiNum) {"); for (int i = 0; i < MAX_ABI_DEF; i++) { if (sequentialAbiDef[i] != null) { ad = sequentialAbiDef[i]; Console.Write(s12 + "case {0,3}: ", ad.abiNum); Console.Write("BspAbiStub" + ad.abiNum + "(cpu, mpCall); "); Console.WriteLine("break;"); } } Console.WriteLine(s12 + "default:"); Console.WriteLine(s16 + "DebugStub.WriteLine(\"HSG: **** Unknown abi call number {0}\","); Console.WriteLine(s16 + "__arglist(mpCall.abiNum));"); Console.WriteLine(s16 + "break;"); Console.WriteLine(s12 + "}"); Console.WriteLine(s8 + "}"); Console.WriteLine(""); } public static void WriteBspAbiStubMethods() { AbiDef ad; for (int i = 0; i < MAX_ABI_DEF; i++) { if (sequentialAbiDef[i] != null) { ad = sequentialAbiDef[i]; WriteBspAbiStubMethod(ad); } } } // Right now, the actual abi is called from Processor.DSI(), hence // all the subsequent calls must have "NoHeapAllocate". But when // the scheduler comes into play, this requirement is no longer holds. // Right now, only Mp ABI functions that have been annotated // with NoHeapAllocate public static bool MethodIsNoHeapAllocation(string methodName) { return true; // this has been fixed since we have ApThread // //if (methodName == "HelloProcessABI" || // methodName == "TestAbiCallOne" || // methodName == "TestAbiCallTwo" || // methodName == "TestAbiCallThree" || // false) { // return true; //} //return false; } public static void WriteBspAbiStubMethod(AbiDef ad) { int curOffset, size; // Console.WriteLine(s8 + "[NoHeapAllocation]"); Console.WriteLine(s8 + "private static unsafe void BspAbiStub" + ad.abiNum + "(int cpu, MpExecution.MpCall mpCall)"); Console.WriteLine(s8 + "{"); Console.WriteLine(s12 + "bool iflag;"); // parameter declaration for (int v = 0; v < ad.shortParamArray.Length; v++) { if (ad.shortParamArray[v] != "" && ad.shortParamArray[v] != "void") { Console.WriteLine(s12 + GetCsType(ad.shortParamArray[v], ad.longParamArray[v]) + " p" + v + ";"); } } if (ad.shortReturnType != "void") { Console.WriteLine(s12 + GetCsTypeForBspAbiStub(ad.shortReturnType, ad.longReturnType) + " retval;"); } Console.WriteLine(""); // get args Console.WriteLine(s12 + "// get args"); Console.WriteLine(s12 + "fixed (byte *baseArg = & mpCall.argBuffer[0] ) {"); curOffset = 0; for (int v = 0; v < ad.shortParamArray.Length; v++) { if (ad.shortParamArray[v] != "" && ad.shortParamArray[v] != "void") { size = GetTypeSize(ad.longParamArray[v]); Console.WriteLine(s16 + " Buffer.MoveMemory((byte*) & p" + v + " , baseArg+" + curOffset + " , " + size + ");"); curOffset += size; } } Console.WriteLine(s12 + "}"); Console.WriteLine(s12 + ""); // Call the actual abi Console.WriteLine(s12 + "// call actual abi"); string actualAbiMethodName = ad.shortMethodName.Substring(4, ad.shortMethodName.Length - 4); string cm = "// "; if (MethodIsNoHeapAllocation(actualAbiMethodName)) { cm = ""; } Console.Write(s12 + cm); if (ad.shortReturnType != "void") { Console.Write("retval = "); } Console.Write(ad.shortClassName + "." + actualAbiMethodName + "("); for (int v = 0; v < ad.shortParamArray.Length; v++) { if (ad.shortParamArray[v] != "" && ad.shortParamArray[v] != "void") { if (v != 0) { Console.Write(", "); } Console.Write("p" + v); } } Console.WriteLine(");"); Console.WriteLine(""); // copy return value if (ad.shortReturnType != "void") { Console.WriteLine(s12 + "// copy return value"); Console.WriteLine(s12 + "fixed (byte *baseRet = & mpCall.retBuffer[0] ) {"); Console.WriteLine(s16 + " Buffer.MoveMemory( baseRet , (byte*) & retval , " + GetTypeSize(ad.longReturnType) + ");"); Console.WriteLine(s12 + "} "); Console.WriteLine(s12 + ""); } // copy arguments back Console.WriteLine(s12 + "// copy arguments back"); Console.WriteLine(s12 + "fixed (byte *baseArg = & mpCall.argBuffer[0] ) {"); curOffset = 0; for (int v = 0; v < ad.shortParamArray.Length; v++) { if (ad.shortParamArray[v] != "" && ad.shortParamArray[v] != "void") { size = GetTypeSize(ad.longParamArray[v]); Console.WriteLine(s16 + " Buffer.MoveMemory(baseArg+" + curOffset + " , (byte*) & p" + v + " , " + size + ");"); curOffset += size; } } Console.WriteLine(s12 + "}"); Console.WriteLine(s12 + ""); // return Console.WriteLine(s12 + "iflag = Processor.DisableInterrupts();"); Console.WriteLine(s12 + "MpExecution.ReturnMpCall(cpu, mpCall.position);"); Console.WriteLine(s12 + "Processor.RestoreInterrupts(iflag);"); Console.WriteLine(s8 + "}"); Console.WriteLine(""); } //////////////////////////////////////////////////////////////// // public static void Generate(string[] args) { genSingStubV1Def = args[0] == "/genSingStubV1Def"; genApAbiStub = args[0] == "/genApAbiStub"; genBspAbiStub = args[0] == "/genBspAbiStub"; genMpSyscallsHeader = args[0] == "/genMpSyscallsHeader"; genMpSyscallsImpl = args[0] == "/genMpSyscallsImpl"; bool genlib = args[0] == "/genlib"; bool deflib = args[0] == "/deflib"; bool defentry = args[0] == "/defentry"; if (!genSingStubV1Def && !genApAbiStub && !genMpSyscallsHeader && !genMpSyscallsImpl && !genBspAbiStub) { throw new Exception("Invalid args .."); } if (genSingStubV1Def) { GenerateSingularityStubV1Def(); return; } if (genApAbiStub) { GenerateApAbiStub(); return; } if (genMpSyscallsHeader) { GenerateMpSyscallsHeader(); return; } if (genMpSyscallsImpl) { GenerateMpSyscallsImpl(); return; } if (genBspAbiStub) { GenerateBspAbiStub(); return; } } // Initialize some tables public static void Initialize() { InitializeTypeConverter(); InitializeParamTable(); // //if (genBspAbiStub) { // for (int i = 0; i < MAX_ABI_DEF; i++) { // sequentialAbiDef[i] = null; // } // } } // Sizes are manually configured // In the future this should come from Bartok public static void InitializeParamTable() { paramTable["void"] = 0; paramTable["int"] = 4; paramTable["unsigned int"] = 4; paramTable["unsigned short"] = 4; paramTable["unsigned char"] = 4; paramTable["wchar_t"] = 4; paramTable["bool"] = 4; paramTable["__int64"] = 8; paramTable["unsigned __int64"] = 8; paramTable["struct Struct_System_TimeSpan"] = 8; paramTable["struct Struct_System_DateTime"] = 8; paramTable["struct Struct_Microsoft_Singularity_V1_Types_SystemType"] = 4; paramTable["struct Struct_Microsoft_Singularity_V1_Threads_ThreadState"] = 4; paramTable["struct Struct_Microsoft_Singularity_V1_Processes_ProcessState"] = 4; paramTable["struct Struct_Microsoft_Singularity_V1_Services_ParameterCode"] = 4; } // We need this because for example "unsigned int should become uint" // Right now we just convert types directly, but there could be some automation // e.g. int * means out int public static void InitializeTypeConverter() { typeConverter["__int64"] = "long"; typeConverter["__int64 *"] = "long*"; typeConverter["__int64 * *"] = "long**"; typeConverter["unsigned __int64"] = "ulong"; typeConverter["unsigned __int64 *"] = "ulong*"; typeConverter["unsigned __int64 * *"] = "ulong**"; typeConverter["unsigned int"] = "uint"; typeConverter["unsigned int *"] = "uint*"; typeConverter["unsigned int * *"] = "uint**"; typeConverter["wchar_t"] = "char"; typeConverter["wchar_t *"] = "char*"; typeConverter["wchar_t * *"] = "char**"; typeConverter["unsigned char"] = "byte"; typeConverter["unsigned char *"] = "byte*"; typeConverter["unsigned char * *"] = "byte **"; typeConverter["unsigned char * * *"] = "byte ***"; typeConverter["unsigned short"] = "ushort"; typeConverter["unsigned short *"] = "ushort *"; typeConverter["unsigned short * *"] = "ushort * *"; typeConverter["struct uintPtr *"] = "UIntPtr"; typeConverter["struct uintPtr * *"] = "UIntPtr*"; } public static int Main(string[] args) { try { Initialize(); Generate(args); } catch (Exception e) { Console.Write(e); return -1; } return 0; } }