]> git.cworth.org Git - apitrace/blob - trace.py
Remove references to megaupload
[apitrace] / trace.py
1 ##########################################################################
2 #
3 # Copyright 2008-2010 VMware, Inc.
4 # All Rights Reserved.
5 #
6 # Permission is hereby granted, free of charge, to any person obtaining a copy
7 # of this software and associated documentation files (the "Software"), to deal
8 # in the Software without restriction, including without limitation the rights
9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 # copies of the Software, and to permit persons to whom the Software is
11 # furnished to do so, subject to the following conditions:
12 #
13 # The above copyright notice and this permission notice shall be included in
14 # all copies or substantial portions of the Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 # THE SOFTWARE.
23 #
24 ##########################################################################/
25
26 """Common trace code generation."""
27
28
29 import specs.stdapi as stdapi
30
31
32 def getWrapperInterfaceName(interface):
33     return "Wrap" + interface.expr
34
35
36 class ComplexValueSerializer(stdapi.OnceVisitor):
37     '''Type visitors which generates serialization functions for
38     complex types.
39     
40     Simple types are serialized inline.
41     '''
42
43     def __init__(self, serializer):
44         stdapi.OnceVisitor.__init__(self)
45         self.serializer = serializer
46
47     def visitVoid(self, literal):
48         pass
49
50     def visitLiteral(self, literal):
51         pass
52
53     def visitString(self, string):
54         pass
55
56     def visitConst(self, const):
57         self.visit(const.type)
58
59     def visitStruct(self, struct):
60         for type, name in struct.members:
61             self.visit(type)
62         print 'static void _write__%s(const %s &value) {' % (struct.tag, struct.expr)
63         print '    static const char * members[%u] = {' % (len(struct.members),)
64         for type, name,  in struct.members:
65             print '        "%s",' % (name,)
66         print '    };'
67         print '    static const trace::StructSig sig = {'
68         print '       %u, "%s", %u, members' % (struct.id, struct.name, len(struct.members))
69         print '    };'
70         print '    trace::localWriter.beginStruct(&sig);'
71         for type, name in struct.members:
72             self.serializer.visit(type, 'value.%s' % (name,))
73         print '    trace::localWriter.endStruct();'
74         print '}'
75         print
76
77     def visitArray(self, array):
78         self.visit(array.type)
79
80     def visitBlob(self, array):
81         pass
82
83     def visitEnum(self, enum):
84         print 'static const trace::EnumValue __enum%s_values[] = {' % (enum.tag)
85         for value in enum.values:
86             print '   {"%s", %s},' % (value, value)
87         print '};'
88         print
89         print 'static const trace::EnumSig __enum%s_sig = {' % (enum.tag)
90         print '   %u, %u, __enum%s_values' % (enum.id, len(enum.values), enum.tag)
91         print '};'
92         print
93
94     def visitBitmask(self, bitmask):
95         print 'static const trace::BitmaskFlag __bitmask%s_flags[] = {' % (bitmask.tag)
96         for value in bitmask.values:
97             print '   {"%s", %s},' % (value, value)
98         print '};'
99         print
100         print 'static const trace::BitmaskSig __bitmask%s_sig = {' % (bitmask.tag)
101         print '   %u, %u, __bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
102         print '};'
103         print
104
105     def visitPointer(self, pointer):
106         self.visit(pointer.type)
107
108     def visitIntPointer(self, pointer):
109         pass
110
111     def visitLinearPointer(self, pointer):
112         self.visit(pointer.type)
113
114     def visitHandle(self, handle):
115         self.visit(handle.type)
116
117     def visitAlias(self, alias):
118         self.visit(alias.type)
119
120     def visitOpaque(self, opaque):
121         pass
122
123     def visitInterface(self, interface):
124         pass
125
126     def visitPolymorphic(self, polymorphic):
127         print 'static void _write__%s(int selector, const %s & value) {' % (polymorphic.tag, polymorphic.expr)
128         print '    switch (selector) {'
129         for cases, type in polymorphic.iterSwitch():
130             for case in cases:
131                 print '    %s:' % case
132             self.serializer.visit(type, 'static_cast<%s>(value)' % (type,))
133             print '        break;'
134         print '    }'
135         print '}'
136         print
137
138
139 class ValueSerializer(stdapi.Visitor):
140     '''Visitor which generates code to serialize any type.
141     
142     Simple types are serialized inline here, whereas the serialization of
143     complex types is dispatched to the serialization functions generated by
144     ComplexValueSerializer visitor above.
145     '''
146
147     def visitLiteral(self, literal, instance):
148         print '    trace::localWriter.write%s(%s);' % (literal.kind, instance)
149
150     def visitString(self, string, instance):
151         if string.length is not None:
152             print '    trace::localWriter.writeString((const char *)%s, %s);' % (instance, string.length)
153         else:
154             print '    trace::localWriter.writeString((const char *)%s);' % instance
155
156     def visitConst(self, const, instance):
157         self.visit(const.type, instance)
158
159     def visitStruct(self, struct, instance):
160         print '    _write__%s(%s);' % (struct.tag, instance)
161
162     def visitArray(self, array, instance):
163         length = '__c' + array.type.tag
164         index = '__i' + array.type.tag
165         print '    if (%s) {' % instance
166         print '        size_t %s = %s;' % (length, array.length)
167         print '        trace::localWriter.beginArray(%s);' % length
168         print '        for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
169         print '            trace::localWriter.beginElement();'
170         self.visit(array.type, '(%s)[%s]' % (instance, index))
171         print '            trace::localWriter.endElement();'
172         print '        }'
173         print '        trace::localWriter.endArray();'
174         print '    } else {'
175         print '        trace::localWriter.writeNull();'
176         print '    }'
177
178     def visitBlob(self, blob, instance):
179         print '    trace::localWriter.writeBlob(%s, %s);' % (instance, blob.size)
180
181     def visitEnum(self, enum, instance):
182         print '    trace::localWriter.writeEnum(&__enum%s_sig, %s);' % (enum.tag, instance)
183
184     def visitBitmask(self, bitmask, instance):
185         print '    trace::localWriter.writeBitmask(&__bitmask%s_sig, %s);' % (bitmask.tag, instance)
186
187     def visitPointer(self, pointer, instance):
188         print '    if (%s) {' % instance
189         print '        trace::localWriter.beginArray(1);'
190         print '        trace::localWriter.beginElement();'
191         self.visit(pointer.type, "*" + instance)
192         print '        trace::localWriter.endElement();'
193         print '        trace::localWriter.endArray();'
194         print '    } else {'
195         print '        trace::localWriter.writeNull();'
196         print '    }'
197
198     def visitIntPointer(self, pointer, instance):
199         print '    trace::localWriter.writeOpaque((const void *)%s);' % instance
200
201     def visitLinearPointer(self, pointer, instance):
202         print '    trace::localWriter.writeOpaque((const void *)%s);' % instance
203
204     def visitHandle(self, handle, instance):
205         self.visit(handle.type, instance)
206
207     def visitAlias(self, alias, instance):
208         self.visit(alias.type, instance)
209
210     def visitOpaque(self, opaque, instance):
211         print '    trace::localWriter.writeOpaque((const void *)%s);' % instance
212
213     def visitInterface(self, interface, instance):
214         print '    trace::localWriter.writeOpaque((const void *)&%s);' % instance
215
216     def visitPolymorphic(self, polymorphic, instance):
217         print '    _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
218
219
220 class ValueWrapper(stdapi.Visitor):
221     '''Type visitor which will generate the code to wrap an instance.
222     
223     Wrapping is necessary mostly for interfaces, however interface pointers can
224     appear anywhere inside complex types.
225     '''
226
227     def visitVoid(self, type, instance):
228         raise NotImplementedError
229
230     def visitLiteral(self, type, instance):
231         pass
232
233     def visitString(self, type, instance):
234         pass
235
236     def visitConst(self, type, instance):
237         pass
238
239     def visitStruct(self, struct, instance):
240         for type, name in struct.members:
241             self.visit(type, "(%s).%s" % (instance, name))
242
243     def visitArray(self, array, instance):
244         # XXX: actually it is possible to return an array of pointers
245         pass
246
247     def visitBlob(self, blob, instance):
248         pass
249
250     def visitEnum(self, enum, instance):
251         pass
252
253     def visitBitmask(self, bitmask, instance):
254         pass
255
256     def visitPointer(self, pointer, instance):
257         print "    if (%s) {" % instance
258         self.visit(pointer.type, "*" + instance)
259         print "    }"
260     
261     def visitIntPointer(self, pointer, instance):
262         pass
263
264     def visitLinearPointer(self, pointer, instance):
265         pass
266
267     def visitHandle(self, handle, instance):
268         self.visit(handle.type, instance)
269
270     def visitAlias(self, alias, instance):
271         self.visit(alias.type, instance)
272
273     def visitOpaque(self, opaque, instance):
274         pass
275     
276     def visitInterface(self, interface, instance):
277         assert instance.startswith('*')
278         instance = instance[1:]
279         print "    if (%s) {" % instance
280         print "        %s = new %s(%s);" % (instance, getWrapperInterfaceName(interface), instance)
281         print "    }"
282     
283     def visitPolymorphic(self, type, instance):
284         # XXX: There might be polymorphic values that need wrapping in the future
285         pass
286
287
288 class ValueUnwrapper(ValueWrapper):
289     '''Reverse of ValueWrapper.'''
290
291     def visitInterface(self, interface, instance):
292         assert instance.startswith('*')
293         instance = instance[1:]
294         print "    if (%s) {" % instance
295         print "        %s = static_cast<%s *>(%s)->m_pInstance;" % (instance, getWrapperInterfaceName(interface), instance)
296         print "    }"
297
298
299 class Tracer:
300     '''Base class to orchestrate the code generation of API tracing.'''
301
302     def __init__(self):
303         self.api = None
304
305     def serializerFactory(self):
306         '''Create a serializer.
307         
308         Can be overriden by derived classes to inject their own serialzer.
309         '''
310
311         return ValueSerializer()
312
313     def trace_api(self, api):
314         self.api = api
315
316         self.header(api)
317
318         # Includes
319         for header in api.headers:
320             print header
321         print
322
323         # Generate the serializer functions
324         types = api.all_types()
325         visitor = ComplexValueSerializer(self.serializerFactory())
326         map(visitor.visit, types)
327         print
328
329         # Interfaces wrapers
330         interfaces = [type for type in types if isinstance(type, stdapi.Interface)]
331         map(self.declareWrapperInterface, interfaces)
332         map(self.implementWrapperInterface, interfaces)
333         print
334
335         # Function wrappers
336         map(self.traceFunctionDecl, api.functions)
337         map(self.traceFunctionImpl, api.functions)
338         print
339
340         self.footer(api)
341
342     def header(self, api):
343         pass
344
345     def footer(self, api):
346         pass
347
348     def traceFunctionDecl(self, function):
349         # Per-function declarations
350
351         if function.args:
352             print 'static const char * __%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
353         else:
354             print 'static const char ** __%s_args = NULL;' % (function.name,)
355         print 'static const trace::FunctionSig __%s_sig = {%u, "%s", %u, __%s_args};' % (function.name, function.id, function.name, len(function.args), function.name)
356         print
357
358     def isFunctionPublic(self, function):
359         return True
360
361     def traceFunctionImpl(self, function):
362         if self.isFunctionPublic(function):
363             print 'extern "C" PUBLIC'
364         else:
365             print 'extern "C" PRIVATE'
366         print function.prototype() + ' {'
367         if function.type is not stdapi.Void:
368             print '    %s __result;' % function.type
369         self.traceFunctionImplBody(function)
370         if function.type is not stdapi.Void:
371             self.wrapRet(function, "__result")
372             print '    return __result;'
373         print '}'
374         print
375
376     def traceFunctionImplBody(self, function):
377         print '    unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
378         for arg in function.args:
379             if not arg.output:
380                 self.unwrapArg(function, arg)
381                 self.serializeArg(function, arg)
382         print '    trace::localWriter.endEnter();'
383         self.invokeFunction(function)
384         print '    trace::localWriter.beginLeave(__call);'
385         for arg in function.args:
386             if arg.output:
387                 self.serializeArg(function, arg)
388                 self.wrapArg(function, arg)
389         if function.type is not stdapi.Void:
390             self.serializeRet(function, "__result")
391         print '    trace::localWriter.endLeave();'
392
393     def invokeFunction(self, function, prefix='__', suffix=''):
394         if function.type is stdapi.Void:
395             result = ''
396         else:
397             result = '__result = '
398         dispatch = prefix + function.name + suffix
399         print '    %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
400
401     def serializeArg(self, function, arg):
402         print '    trace::localWriter.beginArg(%u);' % (arg.index,)
403         self.serializeArgValue(function, arg)
404         print '    trace::localWriter.endArg();'
405
406     def serializeArgValue(self, function, arg):
407         self.serializeValue(arg.type, arg.name)
408
409     def wrapArg(self, function, arg):
410         self.wrapValue(arg.type, arg.name)
411
412     def unwrapArg(self, function, arg):
413         self.unwrapValue(arg.type, arg.name)
414
415     def serializeRet(self, function, instance):
416         print '    trace::localWriter.beginReturn();'
417         self.serializeValue(function.type, instance)
418         print '    trace::localWriter.endReturn();'
419
420     def serializeValue(self, type, instance):
421         serializer = self.serializerFactory()
422         serializer.visit(type, instance)
423
424     def wrapRet(self, function, instance):
425         self.wrapValue(function.type, instance)
426
427     def unwrapRet(self, function, instance):
428         self.unwrapValue(function.type, instance)
429
430     def wrapValue(self, type, instance):
431         visitor = ValueWrapper()
432         visitor.visit(type, instance)
433
434     def unwrapValue(self, type, instance):
435         visitor = ValueUnwrapper()
436         visitor.visit(type, instance)
437
438     def declareWrapperInterface(self, interface):
439         print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
440         print "{"
441         print "public:"
442         print "    %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
443         print "    virtual ~%s();" % getWrapperInterfaceName(interface)
444         print
445         for method in interface.iterMethods():
446             print "    " + method.prototype() + ";"
447         print
448         self.declareWrapperInterfaceVariables(interface)
449         print "};"
450         print
451
452     def declareWrapperInterfaceVariables(self, interface):
453         #print "private:"
454         print "    %s * m_pInstance;" % (interface.name,)
455
456     def implementWrapperInterface(self, interface):
457         print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
458         print '    m_pInstance = pInstance;'
459         print '}'
460         print
461         print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
462         print '}'
463         print
464         for method in interface.iterMethods():
465             self.implementWrapperInterfaceMethod(interface, method)
466         print
467
468     def implementWrapperInterfaceMethod(self, interface, method):
469         print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
470         if method.type is not stdapi.Void:
471             print '    %s __result;' % method.type
472     
473         self.implementWrapperInterfaceMethodBody(interface, method)
474     
475         if method.type is not stdapi.Void:
476             print '    return __result;'
477         print '}'
478         print
479
480     def implementWrapperInterfaceMethodBody(self, interface, method):
481         print '    static const char * __args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
482         print '    static const trace::FunctionSig __sig = {%u, "%s", %u, __args};' % (method.id, interface.name + '::' + method.name, len(method.args) + 1)
483         print '    unsigned __call = trace::localWriter.beginEnter(&__sig);'
484         print '    trace::localWriter.beginArg(0);'
485         print '    trace::localWriter.writeOpaque((const void *)m_pInstance);'
486         print '    trace::localWriter.endArg();'
487         for arg in method.args:
488             if not arg.output:
489                 self.unwrapArg(method, arg)
490                 self.serializeArg(method, arg)
491         print '    trace::localWriter.endEnter();'
492         
493         self.invokeMethod(interface, method)
494
495         print '    trace::localWriter.beginLeave(__call);'
496         for arg in method.args:
497             if arg.output:
498                 self.serializeArg(method, arg)
499                 self.wrapArg(method, arg)
500         if method.type is not stdapi.Void:
501             print '    trace::localWriter.beginReturn();'
502             self.serializeValue(method.type, "__result")
503             print '    trace::localWriter.endReturn();'
504             self.wrapValue(method.type, '__result')
505         print '    trace::localWriter.endLeave();'
506         if method.name == 'QueryInterface':
507             print '    if (ppvObj && *ppvObj) {'
508             print '        if (*ppvObj == m_pInstance) {'
509             print '            *ppvObj = this;'
510             print '        }'
511             for iface in self.api.interfaces:
512                 print r'        else if (riid == IID_%s) {' % iface.name
513                 print r'            *ppvObj = new Wrap%s((%s *) *ppvObj);' % (iface.name, iface.name)
514                 print r'        }'
515             print r'        else {'
516             print r'            os::log("apitrace: warning: unknown REFIID {0x%08lX,0x%04X,0x%04X,{0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X}}\n",'
517             print r'                    riid.Data1, riid.Data2, riid.Data3,'
518             print r'                    riid.Data4[0],'
519             print r'                    riid.Data4[1],'
520             print r'                    riid.Data4[2],'
521             print r'                    riid.Data4[3],'
522             print r'                    riid.Data4[4],'
523             print r'                    riid.Data4[5],'
524             print r'                    riid.Data4[6],'
525             print r'                    riid.Data4[7]);'
526             print r'        }'
527             print '    }'
528         if method.name == 'Release':
529             assert method.type is not stdapi.Void
530             print '    if (!__result)'
531             print '        delete this;'
532
533     def invokeMethod(self, interface, method):
534         if method.type is stdapi.Void:
535             result = ''
536         else:
537             result = '__result = '
538         print '    %sm_pInstance->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
539     
540     def emit_memcpy(self, dest, src, length):
541         print '        unsigned __call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
542         print '        trace::localWriter.beginArg(0);'
543         print '        trace::localWriter.writeOpaque(%s);' % dest
544         print '        trace::localWriter.endArg();'
545         print '        trace::localWriter.beginArg(1);'
546         print '        trace::localWriter.writeBlob(%s, %s);' % (src, length)
547         print '        trace::localWriter.endArg();'
548         print '        trace::localWriter.beginArg(2);'
549         print '        trace::localWriter.writeUInt(%s);' % length
550         print '        trace::localWriter.endArg();'
551         print '        trace::localWriter.endEnter();'
552         print '        trace::localWriter.beginLeave(__call);'
553         print '        trace::localWriter.endLeave();'
554