Upstream version 8.36.161.0
[platform/framework/web/crosswalk.git] / src / third_party / pyelftools / elftools / construct / debug.py
1 """
2 Debugging utilities for constructs
3 """
4 from __future__ import print_function
5 import sys
6 import traceback
7 import pdb
8 import inspect
9 from .core import Construct, Subconstruct
10 from .lib import HexString, Container, ListContainer
11
12
13 class Probe(Construct):
14     """
15     A probe: dumps the context, stack frames, and stream content to the screen
16     to aid the debugging process.
17     See also Debugger.
18     
19     Parameters:
20     * name - the display name
21     * show_stream - whether or not to show stream contents. default is True. 
22       the stream must be seekable.
23     * show_context - whether or not to show the context. default is True.
24     * show_stack - whether or not to show the upper stack frames. default 
25       is True.
26     * stream_lookahead - the number of bytes to dump when show_stack is set.
27       default is 100.
28     
29     Example:
30     Struct("foo",
31         UBInt8("a"),
32         Probe("between a and b"),
33         UBInt8("b"),
34     )
35     """
36     __slots__ = [
37         "printname", "show_stream", "show_context", "show_stack", 
38         "stream_lookahead"
39     ]
40     counter = 0
41     
42     def __init__(self, name = None, show_stream = True, 
43                  show_context = True, show_stack = True, 
44                  stream_lookahead = 100):
45         Construct.__init__(self, None)
46         if name is None:
47             Probe.counter += 1
48             name = "<unnamed %d>" % (Probe.counter,)
49         self.printname = name
50         self.show_stream = show_stream
51         self.show_context = show_context
52         self.show_stack = show_stack
53         self.stream_lookahead = stream_lookahead
54     def __repr__(self):
55         return "%s(%r)" % (self.__class__.__name__, self.printname)
56     def _parse(self, stream, context):
57         self.printout(stream, context)
58     def _build(self, obj, stream, context):
59         self.printout(stream, context)
60     def _sizeof(self, context):
61         return 0
62     
63     def printout(self, stream, context):
64         obj = Container()
65         if self.show_stream:
66             obj.stream_position = stream.tell()
67             follows = stream.read(self.stream_lookahead)
68             if not follows:
69                 obj.following_stream_data = "EOF reached"
70             else:
71                 stream.seek(-len(follows), 1)
72                 obj.following_stream_data = HexString(follows)
73             print
74         
75         if self.show_context:
76             obj.context = context
77         
78         if self.show_stack:
79             obj.stack = ListContainer()
80             frames = [s[0] for s in inspect.stack()][1:-1]
81             frames.reverse()
82             for f in frames:
83                 a = Container()
84                 a.__update__(f.f_locals)
85                 obj.stack.append(a)
86         
87         print("=" * 80)
88         print("Probe", self.printname)
89         print(obj)
90         print("=" * 80)
91
92 class Debugger(Subconstruct):
93     """
94     A pdb-based debugger. When an exception occurs in the subcon, a debugger
95     will appear and allow you to debug the error (and even fix on-the-fly).
96     
97     Parameters:
98     * subcon - the subcon to debug
99     
100     Example:
101     Debugger(
102         Enum(UBInt8("foo"),
103             a = 1,
104             b = 2,
105             c = 3
106         )
107     )
108     """
109     __slots__ = ["retval"]
110     def _parse(self, stream, context):
111         try:
112             return self.subcon._parse(stream, context)
113         except Exception:
114             self.retval = NotImplemented
115             self.handle_exc("(you can set the value of 'self.retval', "
116                 "which will be returned)")
117             if self.retval is NotImplemented:
118                 raise
119             else:
120                 return self.retval
121     def _build(self, obj, stream, context):
122         try:
123             self.subcon._build(obj, stream, context)
124         except Exception:
125             self.handle_exc()
126     def handle_exc(self, msg = None):
127         print("=" * 80)
128         print("Debugging exception of %s:" % (self.subcon,))
129         print("".join(traceback.format_exception(*sys.exc_info())[1:]))
130         if msg:
131             print(msg)
132         pdb.post_mortem(sys.exc_info()[2])
133         print("=" * 80)
134