1827 lines
63 KiB
C#
1827 lines
63 KiB
C#
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// 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("// ");
|
|
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("// File : MpSyscalls.h");
|
|
Console.WriteLine("// Author : t-hargun");
|
|
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("// File : MpSyscalls.cpp");
|
|
Console.WriteLine("// Author : t-hargun");
|
|
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("// File: Singularity/BspAbiStub.cs");
|
|
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.X86;");
|
|
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 haryadi's 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;
|
|
}
|
|
}
|
|
|