FEX/Scripts/StructPackVerifier.py
Ryan Houdek a86109280a StructPackVerifier: Fixes missing cursorkind again
python-clang is getting pretty bad with missing cursor kinds these days.
This was hit from clang-15, will be required for new CI runners
2023-07-26 11:21:16 -07:00

776 lines
26 KiB
Python
Executable File

#!/usr/bin/python3
import clang.cindex
from clang.cindex import CursorKind
from clang.cindex import TypeKind
from clang.cindex import TranslationUnit
import sys
from dataclasses import dataclass, field
import subprocess
import logging
logger = logging.getLogger()
logger.setLevel(logging.WARNING)
# These defines are temporarily defined since python3-clang doesn't yet support these.
# Once this tool gets switched over to C++ then this won't be an issue.
# Type definitions redeclared from `clang/include/clang-c/Index.h`
# Expression that references a C++20 concept.
CursorKind.CONCEPTSPECIALIZATIONEXPR = CursorKind(153),
# Expression that references a C++20 concept.
CursorKind.REQUIRESEXPR = CursorKind(154),
# C++2a std::bit_cast expression.
CursorKind.BUILTINBITCASTEXPR = CursorKind(280)
# a concept declaration.
CursorKind.CONCEPTDECL = CursorKind(604),
@dataclass
class TypeDefinition:
TYPE_UNKNOWN = 0
TYPE_STRUCT = 1
TYPE_UNION = 2
TYPE_FIELD = 3
TYPE_VARDECL = 4
name: str
type: int
def __init__(self, Name, Type):
self.name = Name
self.type = Type
@property
def Name(self):
return self.name
@property
def Type(self):
return self.type
@dataclass
class AliasType:
ALIAS_X86_32 = 0
ALIAS_X86_64 = 1
ALIAS_AARCH64 = 2
ALIAS_WIN32 = 3
ALIAS_WIN64 = 4
Name: str
AliasType: int
def __init__(self, Name, Type):
self.Name = Name
self.AliasType = Type
@dataclass
class StructDefinition(TypeDefinition):
Size: int
Aliases: list
Members: list
ExpectFEXMatch: bool
def __init__(self, Name, Size):
super(StructDefinition, self).__init__(Name, TypeDefinition.TYPE_STRUCT)
self.Size = Size
self.Aliases = []
self.Members = []
self.ExpectFEXMatch = False
@dataclass
class UnionDefinition(TypeDefinition):
Size: int
Aliases: list
Members: list
ExpectFEXMatch: bool
def __init__(self, Name, Size):
super(UnionDefinition, self).__init__(Name, TypeDefinition.TYPE_UNION)
self.Size = Size
self.Aliases = []
self.Members = []
self.ExpectFEXMatch = False
@dataclass
class FieldDefinition(TypeDefinition):
Size: int
OffsetOf: int
Alignment: int
def __init__(self, Name, Size, OffsetOf, Alignment):
super(FieldDefinition, self).__init__(Name, TypeDefinition.TYPE_FIELD)
self.Size = Size
self.OffsetOf = OffsetOf
self.Alignment = Alignment
@dataclass
class VarDeclDefinition(TypeDefinition):
Size: int
Aliases: list
ExpectFEXMatch: bool
Value: str
def __init__(self, Name, Size):
super(VarDeclDefinition, self).__init__(Name, TypeDefinition.TYPE_VARDECL)
self.Size = Size
self.Aliases = []
self.ExpectFEXMatch = False
@dataclass
class ArchDB:
Parsed: bool
ArchName: str
NamespaceScope: list
CurrentNamespace: str
TU: TranslationUnit
Structs: dict
Unions: dict
VarDecls: dict
FieldDecls: list
def __init__(self, ArchName):
self.Parsed = True
self.ArchName = ArchName
self.NamespaceScope = []
self.CurrentNamespace = ""
self.TU = None
self.Structs = {}
self.Unions = {}
self.VarDecls = {}
self.FieldDecls = []
class DBList:
DBs: list
def __init__(self, DB32, DB64, DBAArch64, DBWin32, DBWin64):
self.DBs = [DB32, DB64, DBAArch64, DBWin32, DBWin64]
def FindClangArguments(OriginalArguments):
AddedArguments = ["clang"]
AddedArguments.extend(OriginalArguments)
AddedArguments.extend(["-v", "-x", "c++", "-S", "-"])
Proc = subprocess.Popen(AddedArguments, stderr = subprocess.PIPE, stdin = subprocess.DEVNULL)
NewIncludes = []
BeginSearch = False
while True:
Line = Proc.stderr.readline().strip()
if not Line:
Proc.terminate()
break
if (Line == b"End of search list."):
BeginSearch = False
Proc.terminate()
break
if (BeginSearch == True):
NewIncludes.append("-I" + Line.decode('ascii'))
if (Line == b"#include <...> search starts here:"):
BeginSearch = True
# Add back original arguments
NewIncludes.extend(OriginalArguments)
return NewIncludes
def SetNamespace(Arch):
Arch.CurrentNamespace = ""
for Namespace in Arch.NamespaceScope:
Arch.CurrentNamespace = Arch.CurrentNamespace + Namespace + "::"
def HandleStructDeclCursor(Arch, Cursor, NameOverride = ""):
# Append namespace
CursorName = ""
StructType = Cursor.type
if (len(StructType.spelling) == 0):
CursorName = NameOverride
else:
CursorName = StructType.spelling
if (len(CursorName) != 0):
Arch.NamespaceScope.append(CursorName)
SetNamespace(Arch)
Struct = StructDefinition(
Name = CursorName,
Size = StructType.get_size())
# Handle children
Arch.Structs[Struct.Name] = HandleStructElements(Arch, Struct, Cursor)
# Pop namespace off
if (len(CursorName) != 0):
Arch.NamespaceScope.pop()
SetNamespace(Arch)
return Arch
def HandleUnionDeclCursor(Arch, Cursor, NameOverride = ""):
# Append namespace
CursorName = ""
if (len(Cursor.spelling) == 0):
CursorName = NameOverride
else:
CursorName = Cursor.spelling
if (len(CursorName) != 0):
Arch.NamespaceScope.append(CursorName)
SetNamespace(Arch)
UnionType = Cursor.type
Union = UnionDefinition(
Name = CursorName,
Size = UnionType.get_size())
Arch.Unions[Union.Name] = Union
# Handle children
Arch.Unions[Union.Name] = HandleStructElements(Arch, Union, Cursor)
# Pop namespace off
if (len(CursorName) != 0):
Arch.NamespaceScope.pop()
SetNamespace(Arch)
return Arch
def HandleVarDeclCursor(Arch, Cursor):
CursorName = Cursor.spelling
DeclType = Cursor.type
Def = Cursor.get_definition()
VarDecl = VarDeclDefinition(
Name = CursorName,
Size = DeclType.get_size())
Arch.VarDecls[VarDecl.Name] = HandleVarDeclElements(Arch, VarDecl, Cursor)
return Arch
def HandleVarDeclElements(Arch, VarDecl, Cursor):
for Child in Cursor.get_children():
if (Child.kind == CursorKind.ANNOTATE_ATTR):
if (Child.spelling.startswith("ioctl-alias-")):
Sections = Child.spelling.split("-")
if (Sections[2] == "x86_32"):
VarDecl.Aliases.append(AliasType(Sections[3], AliasType.ALIAS_X86_32))
elif (Sections[2] == "x86_64"):
VarDecl.Aliases.append(AliasType(Sections[3], AliasType.ALIAS_X86_64))
elif (Sections[2] == "aarch64"):
VarDecl.Aliases.append(AliasType(Sections[3], AliasType.ALIAS_AARCH64))
elif (Sections[2] == "win32"):
VarDecl.Aliases.append(AliasType(Sections[3], AliasType.ALIAS_WIN32))
elif (Sections[2] == "win64"):
VarDecl.Aliases.append(AliasType(Sections[3], AliasType.ALIAS_WIN64))
else:
logging.critical ("Can't handle alias type '{0}'".format(Child.spelling))
Arch.Parsed = False
elif (Child.spelling == "fex-match"):
VarDecl.ExpectFEXMatch = True
else:
# Unknown annotation
pass
elif (Child.kind == CursorKind.TYPE_REF or
Child.kind == CursorKind.UNEXPOSED_EXPR or
Child.kind == CursorKind.PAREN_EXPR or
Child.kind == CursorKind.BINARY_OPERATOR
):
pass
return VarDecl
def HandleTypeDefDeclCursor(Arch, Cursor):
TypeDefType = Cursor.underlying_typedef_type
CanonicalType = TypeDefType.get_canonical()
TypeDefName = Cursor.type.get_typedef_name()
if (TypeDefType.kind == TypeKind.ELABORATED and CanonicalType.kind == TypeKind.RECORD):
if (len(TypeDefName) != 0):
HandleTypeDefDecl(Arch, Cursor, TypeDefName)
# Append namespace
Arch.NamespaceScope.append(TypeDefName)
SetNamespace(Arch)
Arch = HandleCursor(Arch, Cursor)
#StructType = Cursor.type
#Struct = StructDefinition(
# Name = TypeDefName,
# Size = CanonicalType.get_size())
#Arch.Structs[TypeDefName] = Struct
## Handle children
#Arch.Structs[TypeDefName] = HandleStructElements(Arch, Struct, Cursor)
# Pop namespace off
Arch.NamespaceScope.pop()
SetNamespace(Arch)
else:
if (len(TypeDefName) != 0):
Def = Cursor.get_definition()
VarDecl = VarDeclDefinition(
Name = TypeDefName,
Size = CanonicalType.get_size())
Arch.VarDecls[VarDecl.Name] = HandleVarDeclElements(Arch, VarDecl, Cursor)
return Arch
def HandleStructElements(Arch, Struct, Cursor):
for Child in Cursor.get_children():
# logging.info ("\t\tStruct/Union Children: Cursor \"{0}{1}\" of kind {2}".format(Arch.CurrentNamespace, Child.spelling, Child.kind))
if (Child.kind == CursorKind.ANNOTATE_ATTR):
if (Child.spelling.startswith("alias-")):
Sections = Child.spelling.split("-")
if (Sections[1] == "x86_32"):
Struct.Aliases.append(AliasType(Sections[2], AliasType.ALIAS_X86_32))
elif (Sections[1] == "x86_64"):
Struct.Aliases.append(AliasType(Sections[2], AliasType.ALIAS_X86_64))
elif (Sections[1] == "aarch64"):
Struct.Aliases.append(AliasType(Sections[2], AliasType.ALIAS_AARCH64))
elif (Sections[1] == "win32"):
Struct.Aliases.append(AliasType(Sections[2], AliasType.ALIAS_WIN32))
elif (Sections[1] == "win64"):
Struct.Aliases.append(AliasType(Sections[2], AliasType.ALIAS_WIN64))
else:
logging.critical ("Can't handle alias type '{0}'".format(Child.spelling))
Arch.Parsed = False
elif (Child.spelling == "fex-match"):
Struct.ExpectFEXMatch = True
else:
# Unknown annotation
pass
elif (Child.kind == CursorKind.FIELD_DECL):
ParentType = Cursor.type
FieldType = Child.type
Field = FieldDefinition(
Name = Child.spelling,
Size = FieldType.get_size(),
OffsetOf = ParentType.get_offset(Child.spelling),
Alignment = FieldType.get_align())
#logging.info ("\t{0}".format(Child.spelling))
#logging.info ("\t\tSize of type: {0}".format(FieldType.get_size()));
#logging.info ("\t\tAlignment of type: {0}".format(FieldType.get_align()));
#logging.info ("\t\tOffsetof of type: {0}".format(ParentType.get_offset(Child.spelling)));
Struct.Members.append(Field)
Arch.FieldDecls.append(Field)
elif (Child.kind == CursorKind.STRUCT_DECL):
ParentType = Cursor.type
FieldType = Child.type
Field = FieldDefinition(
Name = Child.spelling,
Size = FieldType.get_size(),
OffsetOf = ParentType.get_offset(Child.spelling),
Alignment = FieldType.get_align())
#logging.info ("\t{0}".format(Child.spelling))
#logging.info ("\t\tSize of type: {0}".format(FieldType.get_size()));
#logging.info ("\t\tAlignment of type: {0}".format(FieldType.get_align()));
#logging.info ("\t\tOffsetof of type: {0}".format(ParentType.get_offset(Child.spelling)));
Struct.Members.append(Field)
Arch.FieldDecls.append(Field)
Arch = HandleStructDeclCursor(Arch, Child)
elif (Child.kind == CursorKind.UNION_DECL):
Struct = HandleStructElements(Arch, Struct, Child)
#ParentType = Cursor.type
#FieldType = Child.type
#Field = FieldDefinition(
# Name = Child.spelling,
# Size = FieldType.get_size(),
# OffsetOf = ParentType.get_offset(Child.spelling),
# Alignment = FieldType.get_align())
#logging.info ("\t{0}".format(Child.spelling))
#logging.info ("\t\tSize of type: {0}".format(FieldType.get_size()));
#logging.info ("\t\tAlignment of type: {0}".format(FieldType.get_align()));
#logging.info ("\t\tOffsetof of type: {0}".format(ParentType.get_offset(Child.spelling)));
#Struct.Members.append(Field)
#Arch.FieldDecls.append(Field)
#Arch = HandleUnionDeclCursor(Arch, Child)
elif (Child.kind == CursorKind.TYPEDEF_DECL):
Arch = HandleTypeDefDeclCursor(Arch, Child)
else:
Arch = HandleCursor(Arch, Child)
return Struct
def HandleTypeDefDecl(Arch, Cursor, Name):
for Child in Cursor.get_children():
if (Child.kind == CursorKind.UNION_DECL):
pass
elif (Child.kind == CursorKind.STRUCT_DECL):
Arch = HandleStructDeclCursor(Arch, Child, Name)
elif (Child.kind == CursorKind.UNION_DECL):
Arch = HandleUnionDeclCursor(Arch, Child, Name)
elif (Child.kind == CursorKind.TYPEDEF_DECL):
Arch = HandleTypeDefDeclCursor(Arch, Child)
elif (Child.kind == CursorKind.TYPE_REF or
Child.kind == CursorKind.NAMESPACE_REF or
Child.kind == CursorKind.TEMPLATE_REF or
Child.kind == CursorKind.ALIGNED_ATTR):
# Safe to pass on
pass
else:
logging.critical ("Unhandled TypedefDecl {0}-{1}-{2}".format(Child.kind, Child.type.spelling, Child.spelling))
def HandleCursor(Arch, Cursor):
if (Cursor.kind.is_invalid()):
Diags = TU.diagnostics
for Diag in Diags:
logging.warning (Diag.format())
Arch.Parsed = False
return
for Child in Cursor.get_children():
kind = Child.kind
if (kind == CursorKind.TRANSLATION_UNIT):
Arch = HandleCursor(Arch, Child)
elif (kind == CursorKind.FIELD_DECL):
pass
elif (kind == CursorKind.UNION_DECL):
Arch = HandleUnionDeclCursor(Arch, Child)
elif (kind == CursorKind.STRUCT_DECL):
Arch = HandleStructDeclCursor(Arch, Child)
elif (kind == CursorKind.TYPEDEF_DECL):
Arch = HandleTypeDefDeclCursor(Arch, Child)
elif (kind == CursorKind.VAR_DECL):
Arch = HandleVarDeclCursor(Arch, Child)
elif (kind == CursorKind.NAMESPACE):
# Append namespace
Arch.NamespaceScope.append(Child.spelling)
SetNamespace(Arch)
# Handle children
Arch = HandleCursor(Arch, Child)
# Pop namespace off
Arch.NamespaceScope.pop()
SetNamespace(Arch)
elif (kind == CursorKind.TYPE_REF):
# Safe to pass on
pass
else:
Arch = HandleCursor(Arch, Child)
return Arch
def GetDB(Arch, filename, args):
Index = clang.cindex.Index.create()
try:
TU = Index.parse(filename, args=args, options=TranslationUnit.PARSE_INCOMPLETE)
except TranslationUnitLoadError:
Arch.Parsed = False
Diags = TU.diagnostics
for Diag in Diags:
logging.warning (Diag.format())
return
Arch.TU = TU
HandleCursor(Arch, TU.cursor)
# Get diagnostics
Diags = TU.diagnostics
if (len(Diags) != 0):
logging.warning ("Diagnostics from Arch: {0}".format(Arch.ArchName))
for Diag in Diags:
logging.warning (Diag.format())
return Arch
def GetCompar(ComparisonName, DBs):
if (ComparisonName.lower() == "x86_32"):
return DBs.DBs[AliasType.ALIAS_X86_32]
elif (ComparisonName.lower() == "x86_64"):
return DBs.DBs[AliasType.ALIAS_X86_64]
elif (ComparisonName.lower() == "win32"):
return DBs.DBs[AliasType.ALIAS_WIN32]
elif (ComparisonName.lower() == "win64"):
return DBs.DBs[AliasType.ALIAS_WIN64]
elif (ComparisonName.lower() == "aarch64"):
return DBs.DBs[AliasType.ALIAS_AARCH64]
def PrintMissingMembers(Struct1, Struct2):
for Member1 in Struct1.Members:
WasMissing = True
for Member2 in Struct2.Members:
if (Member1.Name == Member2.Name):
WasMissing = False
break
if (WasMissing):
logging.error ("\t'{0}' member '{1}' Doesn't exist in '{2}'".format(Struct1.Name, Member1.Name, Struct2.Name));
def CompareStructs(Struct1, Struct2):
HadWarning = False
HadError = False
# Check if the struct size is a mismatch
if (Struct1.Size != Struct2.Size):
logging.warning ("\t#### Warning: Struct size mismatch. {0} != {1}".format(Struct1.Size, Struct2.Size))
logging.warning ("\t\tMight not be a problem if struct isn't in used inside another struct, or end of object")
HadWarning = True
# Check if the number of members differ
if (len(Struct1.Members) != len(Struct2.Members)):
logging.error ("@@@@ ERROR: Struct fields mismatch! Number of fields don't match! {0} != {1}".format(len(Struct1.Members), len(Struct2.Members)));
PrintMissingMembers(Struct1, Struct2)
PrintMissingMembers(Struct2, Struct1)
HadError = True
else:
# Compare the members themselves
for StructMemberIndex in range(0, len(Struct1.Members)):
Member1 = Struct1.Members[StructMemberIndex]
Member2 = Struct2.Members[StructMemberIndex]
if (Member1.Type == TypeDefinition.TYPE_FIELD):
if (Member1.Size != Member2.Size):
logging.error ("\t@@@@ ERROR: Member '{0}' mismatch Size! {1} != {2}".format(Member1.Name, Member1.Size, Member2.Size));
HadError = True
if (Member1.OffsetOf != Member2.OffsetOf):
logging.error ("\t@@@@ ERROR: Member '{0}' mismatch OffsetOf! {1} != {2}".format(Member1.Name, Member1.OffsetOf, Member2.OffsetOf));
HadError = True
if (Member1.Alignment != Member2.Alignment):
logging.error ("\t@@@@ ERROR: Member '{0}' mismatch Alignment! {1} != {2}".format(Member1.Name, Member1.Alignment, Member2.Alignment));
logging.error ("\t\tProbably not a problem if offset and size matches");
HadWarning = True
else:
logging.critical ("Oops, didn't handle member type {0}".format(Member1.Type))
pass
return not (HadWarning or HadError)
def CompareAliases(DB, DBs):
Passed = True
for StructKey, StructDef in DB.Structs.items():
if (len(StructKey) == 0):
# XXX: Oops, shouldn't have anonymous structs
continue
if (len(StructDef.Aliases) != 0):
logging.info ("Comparing Aliases {0}".format(StructDef.Name))
for Alias in StructDef.Aliases:
OtherDB = DBs.DBs[Alias.AliasType]
OtherStruct = OtherDB.Structs.get(Alias.Name)
if (OtherStruct == None):
logging.critical ("Couldn't find alias {0} in {1} DB".format(Alias.Name, OtherDB.ArchName))
Passed = False
continue
ThisAlias = CompareStructs(StructDef, OtherStruct)
if not (ThisAlias):
logging.error ("Couldn't Alias to Arch {0} successfully".format(OtherDB.ArchName))
Passed &= ThisAlias
for VarDeclKey, VarDecl in DB.VarDecls.items():
if (len(VarDeclKey) == 0):
# XXX: Oops, shouldn't have anonymous vardecls
continue
for Alias in VarDecl.Aliases:
OtherDB = DBs.DBs[Alias.AliasType]
OtherAlias = OtherDB.VarDecls.get(Alias.Name)
if (OtherAlias == None):
logging.critical ("Couldn't find alias {0} in {1} DB".format(Alias.Name, OtherDB.ArchName))
Passed = False
continue
if (VarDecl.Size != OtherAlias.Size):
logging.critical("VarDecl: {0}/{1} didn't match {2}/{3}: {4:08X} != {5:08X}".format(VarDeclKey, DB.ArchName, Alias.Name,
OtherDB.ArchName,
VarDecl.Size, OtherAlias.Size))
Passed = False
continue
return Passed
def CompareCrossArch(DB1, DB2):
Passed = True
for StructKey, StructDef in DB1.Structs.items():
if (len(StructKey) == 0):
# XXX: Oops, shouldn't have anonymous structs
continue
logging.info ("Comparing crossArch {0}".format(StructDef.Name))
if (StructDef.ExpectFEXMatch):
Struct2 = DB2.Structs.get(StructDef.Name)
if (Struct2 == None):
logging.critical ("Couldn't find Struct {0} in {1} DB".format(StructDef.Name, DB2.ArchName))
Passed = False
continue
Passed &= CompareStructs(StructDef, Struct2)
return Passed
def main():
if sys.version_info[0] < 3:
logging.critical ("Python 3 or a more recent version is required.")
if (len(sys.argv) < 2):
print ("usage: %s <options> <Header.hpp> <clang arguments...>" % (sys.argv[0]))
print ("\t-c1 <Type1>: Base Comparison Type");
print ("\t-c2 <Type2>: Second Comparison Type");
print ("\t-win: Parse Windows");
sys.exit ("\t-no-linux: Do not parse Linux");
ParseLinux = True
ParseWindows = False
Header = ""
Comparison1 = ""
Comparison2 = ""
BaseArgs = []
StartOfArgs = 0
# Parse our arguments
ArgIndex = 1
while ArgIndex < len(sys.argv):
Arg = sys.argv[ArgIndex]
if (Arg == "--"):
StartOfArgs = ArgIndex + 1
break;
if (Arg == "-c1"):
ArgIndex += 1
Comparison1 = sys.argv[ArgIndex]
elif (Arg == "-c2"):
ArgIndex += 1
Comparison2 = sys.argv[ArgIndex]
elif (Arg == "-win"):
ParseWindows = True
elif (Arg == "-no-linux"):
ParseLinux = False
else:
Header = Arg
StartOfArgs = ArgIndex + 1
break
# Increment
ArgIndex += 1
# Add arguments for clang
for ArgIndex in range(StartOfArgs, len(sys.argv)):
BaseArgs.append(sys.argv[ArgIndex])
args_x86_32 = [
"-I/usr/i686-linux-gnu/include",
"-O2",
"-m32",
"--target=i686-linux-unknown",
]
args_x86_64 = [
"-I/usr/x86_64-linux-gnu/include",
"-O2",
"--target=x86_64-linux-unknown",
"-D_M_X86_64",
]
args_aarch64 = [
"-I/usr/aarch64-linux-gnu/include",
"-O2",
"--target=aarch64-linux-unknown",
"-D_M_ARM_64",
]
args_x86_win32 = [
"-I/usr/lib/gcc/i686-w64-mingw32/10-win32/include/c++/",
"-I/usr/lib/gcc/i686-w64-mingw32/10-win32/include/c++/i686-w64-mingw32/",
"-O2",
"-m32",
"--target=i686-pc-win32",
]
args_x86_win64 = [
"-I/usr/lib/gcc/x86_64-w64-mingw32/10-win32/include/c++/",
"-I/usr/lib/gcc/x86_64-w64-mingw32/10-win32/include/c++/x86_64-w64-mingw32/",
"-O2",
"--target=x86_64-pc-win32",
]
# Add all the arguments to the different lists
args_x86_32.extend(BaseArgs)
args_x86_64.extend(BaseArgs)
args_aarch64.extend(BaseArgs)
args_x86_win32.extend(BaseArgs)
args_x86_win64.extend(BaseArgs)
# We need to find the default arguments through clang invocations
args_x86_32 = FindClangArguments(args_x86_32)
args_x86_64 = FindClangArguments(args_x86_64)
args_aarch64 = FindClangArguments(args_aarch64)
args_x86_win32 = FindClangArguments(args_x86_win32)
args_x86_win64 = FindClangArguments(args_x86_win64)
Arch_x86_32 = ArchDB("x86_32")
Arch_x86_64 = ArchDB("x86_64")
Arch_aarch64 = ArchDB("aarch64")
Arch_x86_win32 = ArchDB("win32")
Arch_x86_win64 = ArchDB("win64")
if (ParseLinux):
Arch_x86_32 = GetDB(Arch_x86_32, Header, args_x86_32)
Arch_x86_64 = GetDB(Arch_x86_64, Header, args_x86_64)
Arch_aarch64 = GetDB(Arch_aarch64, Header, args_aarch64)
if not (Arch_x86_32.Parsed):
logging.critical ("Couldn't parse:{0}".format(Arch_x86_32.ArchName))
if not (Arch_x86_64.Parsed):
logging.critical ("Couldn't parse:{0}".format(Arch_x86_64.ArchName))
if not (Arch_aarch64.Parsed):
logging.critical ("Couldn't parse:{0}".format(Arch_aarch64.ArchName))
if (ParseWindows):
Arch_x86_win32 = GetDB(Arch_x86_win32, Header, args_x86_win32)
Arch_x86_win64 = GetDB(Arch_x86_win64, Header, args_x86_win64)
if not (Arch_x86_win32.Parsed):
logging.critical ("Couldn't parse:{0}".format(Arch_x86_win32.ArchName))
if not (Arch_x86_win64.Parsed):
logging.critical ("Couldn't parse:{0}".format(Arch_x86_win64.ArchName))
DBs = DBList(Arch_x86_32,
Arch_x86_64,
Arch_aarch64,
Arch_x86_win32,
Arch_x86_win64)
Result = 0
if (len(Comparison1) != 0 and len(Comparison2) != 0):
CompDB1 = GetCompar(Comparison1, DBs)
CompDB2 = GetCompar(Comparison2, DBs)
# Now compare across the two compared architectures
Result = 0 if CompareCrossArch(CompDB1, CompDB2) else 1
elif (len(Comparison1) != 0):
CompDB1 = GetCompar(Comparison1, DBs)
# First compare the aliases to make sure we are matching
Result = 0 if CompareAliases(CompDB1, DBs) else 1
if (Result == 1):
logging.error("Execution environment")
Args = "[ "
for Arg in sys.argv:
Args += Arg + ", "
Args += " ]"
logging.error(Args)
Args = ""
for Arg in sys.argv:
Args += "\"" + Arg + "\" "
logging.error(Args)
return Result
if __name__ == "__main__":
# execute only if run as a script
sys.exit(main())