Ejemplo n.º 1
0
    def setUp(self):
        # Create a configuration
        self.config = Config.Config()
        self.config["library"] = "testlib"

        # Create a basic library for testing
        self.library = Library.Library("test")

        voidType = Library.Type("void")
        intType = Library.Type("int")

        f = Library.Function("func1", voidType)
        p = Library.Parameter("parameter", intType)
        f.parameters[p.name] = p
        self.library.functions[f.name] = f

        f = Library.Function("func2", intType)
        p1 = Library.Parameter("p1", intType)
        p2 = Library.Parameter("p2", intType)
        f.parameters[p1.name] = p1
        f.parameters[p2.name] = p2
        self.library.functions[f.name] = f

        # Register some types
        self.library.typeMap["int"] = "int"
        self.library.typeMap["void"] = "void"

        # Define platform properties
        self.platform = SymbianPlatform(self.config)
Ejemplo n.º 2
0
    def testGlTracerGeneration(self):
        # Parse the preprocessed GL header
        l = Library.Library("GL", "libgles_cm_orig.dll")
        l.merge(Parser.parseSource(open("data/gl-cpp.h").read()))
        l.merge(Parser.parseSource(open("data/egl-cpp.h").read()))
        defFile = open("data/opengles11u.def").read()
        for function, ordinal in Parser.parseDefFile(defFile):
            if function in l.functions:
                l.functions[function].ordinal = ordinal

        # Add a custom function hook
        customSource = """
    GLenum xglGetError(void)
    {
      wtf();
    }
    """
        l.merge(Parser.parseSource(customSource))
        T = Library.Type

        # GL types
        l.typeMap[T("GLenum")] = "int"
        l.typeMap[T("GLint")] = "int"
        l.typeMap[T("GLintptr")] = "int"
        l.typeMap[T("GLuint")] = "int"
        l.typeMap[T("GLboolean")] = "int"
        l.typeMap[T("GLbitfield")] = "int"
        l.typeMap[T("GLsizei")] = "int"
        l.typeMap[T("GLsizeiptr")] = "int"
        l.typeMap[T("GLfixed")] = "int"
        l.typeMap[T("GLclampx")] = "int"
        l.typeMap[T("GLubyte")] = "byte"
        l.typeMap[T("GLshort")] = "short"
        l.typeMap[T("GLclampf")] = "float"
        l.typeMap[T("GLfloat")] = "float"
        l.typeMap[T("void")] = "void"

        # EGL types
        l.typeMap[T("EGLboolean")] = "int"
        l.typeMap[T("EGLint")] = "int"
        l.typeMap[T("EGLDisplay")] = "int"
        l.typeMap[T("EGLSurface")] = "int"
        l.typeMap[T("EGLContext")] = "int"
        l.typeMap[T("EGLConfig")] = "int"
        l.typeMap[T("EGLBoolean")] = "int"
        l.typeMap[T("NativeDisplayType")] = "int"
        l.typeMap[T("NativeWindowType")] = "pointer"
        l.typeMap[T("NativePixmapType")] = "pointer"

        # Mark eglTerminate as a terminator
        l.functions["eglTerminate"].isTerminator = True

        g = TracerGenerator(self.config, self.platform, [l])
        g.generate(open("generator_test_output.txt", "w"))
Ejemplo n.º 3
0
 def processEvent(self, event, implicitStateValue = None):
   assert event.name in self.library.functions, "Function not found in library: %s" % event.name
   
   function       = self.library.functions[event.name]
   stateModifiers = []
   
   def getStatePathForValue(name):
     if name is None:
       relation = function.retStateRelation
     else:
       relation = function.parameters[name].stateRelation
     if relation:
       try:
         return relation.path
       except AttributeError:
         # The copy relation does it this way
         return relation.destPath
   
   # Sort the values by their state paths (shortest first)
   values = event.values.items()
   values.sort(cmp = lambda v1, v2: cmp(getStatePathForValue(v1[0]), getStatePathForValue(v2[0])))
   
   for name, value in values:
     # Get the state path
     if name is None:
       relation = function.retStateRelation
     else:
       relation = function.parameters[name].stateRelation
     
     if self.decorateValues:
       value = StringUtils.decorateValue(self.library, function, name, value)
    
     # Write the state value
     if relation and self._updateState(event, relation, value):
       stateModifiers.append(name)
   
   for relation in function.stateRelations:
     if isinstance(relation, Library.StateRelationModify):
       if implicitStateValue is None:
         # Use a special placeholder value for completely unknown state values
         self._updateState(event, relation, ImplicitStateValue())
       else:
         # When we know the exact value, this relation becomes a "set" relation
         self._updateState(event, Library.StateRelationSet(relation.path), implicitStateValue)
     elif relation.__class__ in (Library.StateRelationSet, Library.StateRelationGet, Library.StateRelationCopy):
       self._updateState(event, relation, None)
     else:
       raise RuntimeError("Unknown state relation: %s" % relation)
   
   if self.collectEffectiveEvents and self.isStateAccessingEvent(event):
     self.effectiveEvents.add(event)
   return stateModifiers
Ejemplo n.º 4
0
    def testDefFile(self):
        l = Parser.parseSource(testHeader)

        # FIXME: hardcode the function pointer since we don't parse those yet
        l.functions["funcPointer"] = Library.Function("funcPointer", "void")

        for function, ordinal in Parser.parseDefFile(testDefFile):
            l.functions[function].ordinal = ordinal

        # check that all ordinals were read
        for f in l.functions.values():
            assert f.ordinal is not None

        # check overlapping ordinals in input
        try:
            Parser.parseDefFile(testBadDefFile)
            self.fail("ValueError not raised.")
        except ValueError:
            pass
Ejemplo n.º 5
0
        def registerArray(event, name, value):
            function = self.analyzer.lookupFunction(event)

            if name:
                cType = function.parameters[name].type
            else:
                cType = function.type

            # Extract an essential type for the array discarding all qualifiers and modifiers
            cType = Library.Type(cType.name)

            # Get the real, non-typedef'd type as well
            realType = library.resolveType(cType)

            # If this is a void type, use the original type instead
            if realType.name == "void":
                cType = arrayTypeMap[value.__class__]

            arrayTypes[arrayId(value)] = cType

            # If this is an object array, register the objects too
            if isinstance(value, Trace.ObjectArrayValue):
                for obj in value:
                    registerObject(event, name, obj)
Ejemplo n.º 6
0
def parseSource(source):
    """
  Parses the given source string and adds all found functions
  to the library.
    
  @param header:    Source text
    
  @returns: A library containing the parsed functions
  """
    task = Task.startTask("parser", "Parsing type declarations", len(source))
    library = Library()

    # Read the type definitions
    typedefs = []
    for match, pos, l in typedefDecl.scanString(source):
        task.updateProgress(pos)
        # Map enumerations to integers
        if match[0] == "enum":
            name = match[-1]
            type = Type("int")
            for i, e in enumerate(match[1]):
                enumeration, value = e
                if value is None:
                    value = i
                type.addSymbolicConstant(enumeration, value)
                library.constants[enumeration] = value
        else:
            name, type = match[0]
        library.typeDefs[Type(name)] = type
    task.finish()

    # Read preprocessor constants
    task = Task.startTask("parser", "Parsing preprocessor constants",
                          len(source))
    for match, pos, l in preprocessorCommand.scanString(source):
        task.updateProgress(pos)
        # Only look for #define
        if match.command != "define":
            continue

        # Only accept integral constants
        try:
            value = parseInteger(None, None, [match.value])
        except ValueError:
            continue

        library.constants[match.name] = value
    task.finish()

    def where(pos):
        return "Line %d, column %s" % (lineno(pos, source), col(pos, source))

    task = Task.startTask("parser", "Parsing functions", len(source))
    for match, pos, l in function.scanString(source):
        task.updateProgress(pos)
        name, type = match.name[0]
        if not name: continue
        f = Function(name, type)
        f.language = "c"
        for name, type in match.args:
            if not name or not type:
                continue
            f.parameters[name] = Parameter(name, type)

        # Grab the code if any
        if match.body:
            f.body = match.body

        library.functions[f.name] = f
    task.finish()
    return library
Ejemplo n.º 7
0
def parseSource(source):
  """
  Parses the given source string and adds all found functions
  to the library.
    
  @param header:    Source text
    
  @returns: A library containing the parsed functions
  """
  task    = Task.startTask("parser", "Parsing type declarations", len(source))
  library = Library()

  # Read the type definitions
  typedefs = []
  for match, pos, l in typedefDecl.scanString(source):
    task.updateProgress(pos)
    # Map enumerations to integers
    if match[0] == "enum":
      name = match[-1]
      type = Type("int")
      for i, e in enumerate(match[1]):
        enumeration, value = e
        if value is None:
          value = i
        type.addSymbolicConstant(enumeration, value)
        library.constants[enumeration] = value
    else:
      name, type = match[0]
    library.typeDefs[Type(name)] = type
  task.finish()

  # Read preprocessor constants
  task = Task.startTask("parser", "Parsing preprocessor constants", len(source))
  for match, pos, l in preprocessorCommand.scanString(source):
    task.updateProgress(pos)
    # Only look for #define
    if match.command != "define":
      continue
    
    # Only accept integral constants
    try:
      value = parseInteger(None, None, [match.value])
    except ValueError:
      continue
    
    library.constants[match.name] = value
  task.finish()

  def where(pos):
    return "Line %d, column %s" % (lineno(pos, source), col(pos, source))
  
  task = Task.startTask("parser", "Parsing functions", len(source))
  for match, pos, l in function.scanString(source):
    task.updateProgress(pos)
    name, type = match.name[0]
    if not name: continue
    f = Function(name, type)
    f.language = "c"
    for name, type in match.args:
      if not name or not type:
        continue
      f.parameters[name] = Parameter(name, type)

    # Grab the code if any
    if match.body:
      f.body = match.body

    library.functions[f.name] = f
  task.finish()
  return library
Ejemplo n.º 8
0
    def prepare(self):
        # Shorthand for various objects
        config = self.config
        lib = self.library

        # Parse the sources
        for fileName in config.get("apiheaders", []):
            Log.notice("Parsing functions from '%s'." % fileName)
            source = self.parserTool.readSource(fileName)
            newLib = Parser.parseSource(source)
            for f in newLib.functions.values():
                f.headerName = fileName
            for f in newLib.functions.values():
                Log.debug("%s %s(%s)" % (f.type, f.name, ", ".join(
                    ["%s %s" % (t.type, p) for p, t in f.parameters.items()])))
            if not newLib.functions:
                Log.warn("No new functions found.")
            else:
                Log.notice("%d functions found." % len(newLib.functions))
            lib.merge(newLib)

        # Load the hooks
        self.parserTool.loadHooks()

        def parseBool(s):
            return bool(int(s))

        # Read the typemap
        for typeDecl, mapping in self.config.types.items():
            attrs = self.config.types[typeDecl].attrs
            name, type = Parser.parseVariableDeclaration(typeDecl + " dummy")
            assert name == "dummy"
            # If this is a class mapping, create the class if it doesn't already exist
            if mapping == "object":
                if not mapping in self.library.classes:
                    cls = Library.Class(type)
                    if "namespace" in attrs:
                        cls.namespacePath = attrs["namespace"].split(".")
                    self.library.classes[type] = cls
            # Patch the default decoration hint into all matching types
            if "decorationhint" in attrs:
                for function in self.library.functions.values():
                    for t in [p.type for p in function.parameters.values()
                              ] + [function.type]:
                        if t == type:
                            t.decorationHint = attrs["decorationhint"]
            self.library.typeMap[type] = str(mapping)

        # Patch in some function-specific attributes
        for function in config.functions.keys():
            if not function in lib.functions:
                self.fail(
                    "Attributes specified for non-existent function '%s'." %
                    function)
            attrs = config.functions[function].attrs
            if "terminator" in attrs:
                lib.functions[function].isTerminator = parseBool(
                    attrs["terminator"])
            if "generate" in attrs:
                lib.functions[function].generate = parseBool(attrs["generate"])
            if "runtimestate" in attrs:
                lib.functions[function].runtimeStateTracking = parseBool(
                    attrs["runtimestate"])
            if "framemarker" in attrs:
                lib.functions[function].isFrameMarker = parseBool(
                    attrs["framemarker"])
            if "staticlinkage" in attrs:
                lib.functions[function].staticLinkage = parseBool(
                    attrs["staticlinkage"])
            if "rendercall" in attrs:
                lib.functions[function].isRenderCall = parseBool(
                    attrs["rendercall"])
            if "passthrough" in attrs:
                lib.functions[function].passthrough = parseBool(
                    attrs["passthrough"])

            if not isinstance(config.functions[function], Config.Group):
                self.fail(
                    "Syntax error: State map definition for function '%s' is missing braces."
                    % function)

            # Argument to state mapping
            reservedNames = ["@return", "@modify", "@set", "@get", "@copy"]
            funcAttrs = attrs
            for arg, parameter in config.functions[function].items():
                # Check that this is a valid parameter
                if not arg in reservedNames and not arg in lib.functions[
                        function].parameters:
                    self.fail(
                        "State mapping for nonexistent parameter '%s' of function '%s' specified."
                        % (arg, function))

                if arg in ["@copy"] and parseBool(
                        funcAttrs.get("runtimestate", "0")):
                    Log.warn(
                        "Function %s state relation %s not implemented for runtime state tracking."
                        % (function, arg))

                # Read the parameter-specific attributes
                attrs = config.functions[function][arg].attrs
                if "decoration" in attrs:
                    lib.functions[function].parameters[arg].decoration = attrs[
                        "decoration"]
                if "decorationhint" in attrs:
                    lib.functions[function].parameters[
                        arg].decorationHint = attrs["decorationhint"]
                if "out" in attrs:
                    lib.functions[function].parameters[arg].isOut = parseBool(
                        attrs["out"])
                if "object_class" in attrs:
                    # Create a function-local type so that this parameter type is an object only for this function
                    if arg == "@return":
                        type = lib.functions[function].type
                    else:
                        type = lib.functions[function].parameters[arg].type
                    # Override the type's name so that it will refer to the new object class
                    # while still using the original C type under the hood
                    newType = copy.deepcopy(type)
                    newType.isObject = True
                    newType.name = attrs["object_class"]
                    if arg == "@return":
                        lib.functions[function].type = newType
                    else:
                        lib.functions[function].parameters[arg].type = newType
                    # Check that this class exists
                    classType = Library.Type(attrs["object_class"])
                    if not classType in self.library.classes:
                        self.fail("Undefined object class '%s'." % classType)

                # Do we have a meta type?
                if "metatype" in config.functions[function][arg]:
                    metaGroup = config.functions[function][arg].metatype

                    try:
                        metaType = Library.MetaType(metaGroup.attrs["class"])
                    except KeyError:
                        self.fail(
                            "Meta type for parameter '%s' does not define class."
                            % arg)

                    # Is this an array parameter?
                    if metaType.name == "array":
                        metaType.values["size"] = Library.MetaValue(
                            "size", metaGroup.attrs.get("size", 1))
                        if "type" in metaGroup.attrs:
                            metaType.values["type"] = Library.MetaValue(
                                "type", metaGroup.attrs["type"])
                            if metaGroup.attrs["type"] == "object":
                                if not "object_class" in metaGroup.attrs:
                                    self.fail(
                                        "Required metatype attribute object_class missing"
                                    )
                                metaType.values[
                                    "object_class"] = Library.MetaValue(
                                        "object_class",
                                        metaGroup.attrs["object_class"])
                    # How about an image parameter?
                    elif metaType.name == "image":
                        metaType.values["stride"] = Library.MetaValue(
                            "stride", metaGroup.attrs.get("stride", "width"))
                        metaType.values["height"] = Library.MetaValue(
                            "height", metaGroup.attrs.get("height", "height"))
                        metaType.values["components"] = Library.MetaValue(
                            "components",
                            metaGroup.attrs.get("components", "1"))
                        metaType.values["type"] = Library.MetaValue(
                            "type", metaGroup.attrs.get("type", "byte"))
                    else:
                        self.fail("Unknown meta type class '%s'." % metaclass)

                    Log.debug("Meta type: %s.%s: %s" %
                              (function, arg, metaType.name))

                    # Get the conditions for different meta values
                    if isinstance(metaGroup, Config.List):
                        for item in metaGroup:
                            predicate = item.attrs["condition"]
                            predicateValue = item.attrs["value"]
                            result = item.attrs["result"]
                            metaType.values[item].addPredicate(
                                predicate, predicateValue, result)
                            Log.debug(
                                "Meta type condition: If %s is %s, then %s = %s"
                                % (predicate, predicateValue, item, result))
                    elif isinstance(metaGroup, Config.Group):
                        Log.error(
                            "Meta type variations for parameter '%s' represented in a group instead of a list."
                            % arg)

                    # Record the meta type
                    lib.functions[function].parameters[arg].metaType = metaType

                # Is this a short-hand state mapping?
                try:
                    path = parameter.split(".")
                except AttributeError:
                    # Try the expanded form of a nested attribute set
                    try:
                        path = (
                            config.functions[function][arg].state).split(".")
                    except AttributeError:
                        path = []

                # Check that we even have a state structure
                if path and not "state" in config:
                    Log.warn("State structure not defined.")
                    continue

                # Parse special state mapping relations
                relation = None
                checkPaths = []
                if arg == "@copy":
                    relation = Library.StateRelationCopy(
                        attrs["src"].split("."), attrs["dest"].split("."))
                    checkPaths = [relation.sourcePath, relation.destPath]
                elif arg == "@get":
                    relation = Library.StateRelationGet(path)
                    checkPaths = [relation.path]
                elif arg == "@set":
                    relation = Library.StateRelationSet(path)
                    checkPaths = [relation.path]
                elif arg == "@modify":
                    relation = Library.StateRelationModify(path)
                    checkPaths = [relation.path]
                # Empty mapping?
                elif not "".join(path):
                    continue

                if relation:
                    for path in checkPaths:
                        if traverseStatePath(config, path) is None:
                            self.fail(
                                "Relation state path '%s' for function '%s' does not exist."
                                % (".".join(path), function))
                    Log.debug("State relation: %s %s" % (function, relation))
                    lib.functions[function].stateRelations.append(relation)
                    continue

                Log.debug("State mapping: %s.%s -> %s" %
                          (function, arg, ".".join(path)))

                # Determine the parameter type
                type = None

                if arg == "@return":
                    type = lib.functions[function].type
                else:
                    type = lib.functions[function].parameters[arg].type

                # If this is a runtime mapping, check that the parameter is of a supported type
                if lib.functions[function].runtimeStateTracking and type and \
                   lib.getNativeType(type) in ["float", "double"]:
                    self.fail(
                        "Values of type '%s' can not be saved to the runtime state tree"
                        % type)
                    continue

                node = traverseStatePath(config, path)
                if node is None:
                    self.fail(
                        "State path '%s' for function '%s' does not exist." %
                        (".".join(path), function))

                # Save the mapping
                if arg == "@return":
                    lib.functions[
                        function].retStateRelation = Library.StateRelationSet(
                            path)
                else:
                    lib.functions[function].parameters[
                        arg].stateRelation = Library.StateRelationSet(path)
Ejemplo n.º 9
0
    def loadSymbolMap(self):
        config = self.config
        lib = self.library
        demangler = Tools.SymbolDecoder(config)

        # Set default library name
        if "library" in config:
            for function in lib.functions.values():
                function.libName = config.library

        # Read in the export ordinals
        if "deffiles" in config:
            for defFile in config.deffiles:
                for function, ordinal in Parser.parseDefFile(
                        open(config.getRelativePath(defFile)).read()):
                    if function in lib.functions:
                        lib.functions[function].exportOrdinal = ordinal
                        Log.debug("%s is exported at %d" % (function, ordinal))
                    # The function was not found in the library, so let's check whether it is a C++ symbol
                    elif demangler.isMangled(function):
                        function = demangler.decode(function)
                        if function in lib.functions:
                            # Save the ordinal and mark the function as C++
                            lib.functions[function].exportOrdinal = ordinal
                            lib.functions[function].language = "c++"
                            Log.debug("%s is exported at %d" %
                                      (function, ordinal))

        # Read the link ordinals and DLL information
        if "symbol_map" in config:
            defaultLibName = None
            for fileName, libName in config.symbol_map.items():
                if fileName == "default":
                    defaultLibName = libName
                    continue

                # Is it a .DEF file
                if fileName.endswith(".def"):
                    for function, ordinal in Parser.parseDefFile(
                            open(config.getRelativePath(fileName)).read()):
                        if function in lib.functions:
                            lib.functions[function].ordinal = ordinal
                            lib.functions[function].libName = libName
                            Log.debug("%s is at %s:%d" %
                                      (function, libName, ordinal))
                        # The function was not found in the library, so let's check whether it is a C++ symbol
                        elif demangler.isMangled(function):
                            function = demangler.decode(function)
                            if function in lib.functions:
                                # Save the ordinal and mark the function as C++
                                lib.functions[function].ordinal = ordinal
                                lib.functions[function].libName = libName
                                lib.functions[function].language = "c++"
                                Log.debug("%s is at %s:%d" %
                                          (function, libName, ordinal))
                else:  # it's a header file
                    assert fileName.endswith(".h")
                    for function in lib.functions.values():
                        if function.headerName == fileName:
                            function.libName = libName
            # Generate passthrough functions for internal symbols
            if defaultLibName:
                assert self.project.platform.requireOrdinals, "Default symbol mapping can only be used in platforms that use symbol ordinals"
                assert "max_internal_ordinal" in config, "max_internal_ordinal must be defined when using a default symbol mapping"
                ordinals = range(1, int(config["max_internal_ordinal"]) + 1)
                for function in lib.functions.values():
                    if function.exportOrdinal in ordinals:
                        ordinals.remove(function.exportOrdinal)
                for ordinal in ordinals:
                    name = "_trInternal%d" % ordinal
                    f = Library.Function(name, Library.Type("void"))
                    f.language = "c"
                    f.ordinal = ordinal
                    f.exportOrdinal = ordinal
                    f.libName = defaultLibName
                    lib.functions[name] = f
                    Log.debug("%s is at %s:%d" %
                              (name, defaultLibName, ordinal))
Ejemplo n.º 10
0
def create(project, options, args):
    """Create a new Tracy project. [config file] [targets]"""

    if not args or len(args) < 1:
        fail("Configuration file name missing.")

    configName = args[0]
    targetNames = args[1:]

    # Load the configuration file
    project.config.loadFile(configName)
    for path in project.config.paths:
        Resource.paths.append(path)
    config = project.config

    try:
        # Create the platform and read it's configuration if it exists.
        platform = Platform.platforms[options.platform](config)
    except KeyError:
        fail("No such platform. Use one of %s" %
             ", ".join(Platform.platforms.keys()))

    projectName = config.name.lower()

    Log.notice(
        heading("Creating Tracy project '%s' for %s" %
                (projectName, platform.name)))

    # Initialize the project
    lib = Library.Library(name=config.name)
    project.library = lib
    project.platform = platform

    def prepareTarget(targetName):
        if targetName in project.targets:
            return

        if not targetName in Target.targets:
            fail("Bad target name '%s'." % targetName)
            return

        targetClass = Target.targets[targetName]
        for dep in targetClass.dependencies:
            if not dep in project.targets:
                prepareTarget(dep)

        Log.notice("Preparing target %d of %d: %s." %
                   (len(project.targets) + 1, len(targetNames), targetName))
        target = targetClass(project)
        target.prepare()
        target.validate()
        project.targets[targetName] = target

    # Prepare the targets
    if not targetNames:
        targetNames = Target.targets.keys()

    for targetName in targetNames:
        prepareTarget(targetName)

    # Save the project
    projectPath = options.output and options.output or ("%s.tcy" % projectName)
    project.save(projectPath)

    Log.notice("Tracy project '%s' saved to '%s'." %
               (projectName, projectPath))