]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - packages/Python/lldbsuite/test/lldbutil.py
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / packages / Python / lldbsuite / test / lldbutil.py
1 """
2 This LLDB module contains miscellaneous utilities.
3 Some of the test suite takes advantage of the utility functions defined here.
4 They can also be useful for general purpose lldb scripting.
5 """
6
7 from __future__ import print_function
8 from __future__ import absolute_import
9
10 # System modules
11 import collections
12 import os
13 import re
14 import sys
15 import time
16
17 # Third-party modules
18 from six import StringIO as SixStringIO
19 import six
20
21 # LLDB modules
22 import lldb
23
24
25 # ===================================================
26 # Utilities for locating/checking executable programs
27 # ===================================================
28
29 def is_exe(fpath):
30     """Returns True if fpath is an executable."""
31     return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
32
33
34 def which(program):
35     """Returns the full path to a program; None otherwise."""
36     fpath, fname = os.path.split(program)
37     if fpath:
38         if is_exe(program):
39             return program
40     else:
41         for path in os.environ["PATH"].split(os.pathsep):
42             exe_file = os.path.join(path, program)
43             if is_exe(exe_file):
44                 return exe_file
45     return None
46
47 # ===================================================
48 # Disassembly for an SBFunction or an SBSymbol object
49 # ===================================================
50
51
52 def disassemble(target, function_or_symbol):
53     """Disassemble the function or symbol given a target.
54
55     It returns the disassembly content in a string object.
56     """
57     buf = SixStringIO()
58     insts = function_or_symbol.GetInstructions(target)
59     for i in insts:
60         print(i, file=buf)
61     return buf.getvalue()
62
63 # ==========================================================
64 # Integer (byte size 1, 2, 4, and 8) to bytearray conversion
65 # ==========================================================
66
67
68 def int_to_bytearray(val, bytesize):
69     """Utility function to convert an integer into a bytearray.
70
71     It returns the bytearray in the little endian format.  It is easy to get the
72     big endian format, just do ba.reverse() on the returned object.
73     """
74     import struct
75
76     if bytesize == 1:
77         return bytearray([val])
78
79     # Little endian followed by a format character.
80     template = "<%c"
81     if bytesize == 2:
82         fmt = template % 'h'
83     elif bytesize == 4:
84         fmt = template % 'i'
85     elif bytesize == 4:
86         fmt = template % 'q'
87     else:
88         return None
89
90     packed = struct.pack(fmt, val)
91     return bytearray(packed)
92
93
94 def bytearray_to_int(bytes, bytesize):
95     """Utility function to convert a bytearray into an integer.
96
97     It interprets the bytearray in the little endian format. For a big endian
98     bytearray, just do ba.reverse() on the object before passing it in.
99     """
100     import struct
101
102     if bytesize == 1:
103         return bytes[0]
104
105     # Little endian followed by a format character.
106     template = "<%c"
107     if bytesize == 2:
108         fmt = template % 'h'
109     elif bytesize == 4:
110         fmt = template % 'i'
111     elif bytesize == 4:
112         fmt = template % 'q'
113     else:
114         return None
115
116     unpacked = struct.unpack_from(fmt, bytes)
117     return unpacked[0]
118
119
120 # ==============================================================
121 # Get the description of an lldb object or None if not available
122 # ==============================================================
123 def get_description(obj, option=None):
124     """Calls lldb_obj.GetDescription() and returns a string, or None.
125
126     For SBTarget, SBBreakpointLocation, and SBWatchpoint lldb objects, an extra
127     option can be passed in to describe the detailed level of description
128     desired:
129         o lldb.eDescriptionLevelBrief
130         o lldb.eDescriptionLevelFull
131         o lldb.eDescriptionLevelVerbose
132     """
133     method = getattr(obj, 'GetDescription')
134     if not method:
135         return None
136     tuple = (lldb.SBTarget, lldb.SBBreakpointLocation, lldb.SBWatchpoint)
137     if isinstance(obj, tuple):
138         if option is None:
139             option = lldb.eDescriptionLevelBrief
140
141     stream = lldb.SBStream()
142     if option is None:
143         success = method(stream)
144     else:
145         success = method(stream, option)
146     if not success:
147         return None
148     return stream.GetData()
149
150
151 # =================================================
152 # Convert some enum value to its string counterpart
153 # =================================================
154
155 def state_type_to_str(enum):
156     """Returns the stateType string given an enum."""
157     if enum == lldb.eStateInvalid:
158         return "invalid"
159     elif enum == lldb.eStateUnloaded:
160         return "unloaded"
161     elif enum == lldb.eStateConnected:
162         return "connected"
163     elif enum == lldb.eStateAttaching:
164         return "attaching"
165     elif enum == lldb.eStateLaunching:
166         return "launching"
167     elif enum == lldb.eStateStopped:
168         return "stopped"
169     elif enum == lldb.eStateRunning:
170         return "running"
171     elif enum == lldb.eStateStepping:
172         return "stepping"
173     elif enum == lldb.eStateCrashed:
174         return "crashed"
175     elif enum == lldb.eStateDetached:
176         return "detached"
177     elif enum == lldb.eStateExited:
178         return "exited"
179     elif enum == lldb.eStateSuspended:
180         return "suspended"
181     else:
182         raise Exception("Unknown StateType enum")
183
184
185 def stop_reason_to_str(enum):
186     """Returns the stopReason string given an enum."""
187     if enum == lldb.eStopReasonInvalid:
188         return "invalid"
189     elif enum == lldb.eStopReasonNone:
190         return "none"
191     elif enum == lldb.eStopReasonTrace:
192         return "trace"
193     elif enum == lldb.eStopReasonBreakpoint:
194         return "breakpoint"
195     elif enum == lldb.eStopReasonWatchpoint:
196         return "watchpoint"
197     elif enum == lldb.eStopReasonExec:
198         return "exec"
199     elif enum == lldb.eStopReasonSignal:
200         return "signal"
201     elif enum == lldb.eStopReasonException:
202         return "exception"
203     elif enum == lldb.eStopReasonPlanComplete:
204         return "plancomplete"
205     elif enum == lldb.eStopReasonThreadExiting:
206         return "threadexiting"
207     else:
208         raise Exception("Unknown StopReason enum")
209
210
211 def symbol_type_to_str(enum):
212     """Returns the symbolType string given an enum."""
213     if enum == lldb.eSymbolTypeInvalid:
214         return "invalid"
215     elif enum == lldb.eSymbolTypeAbsolute:
216         return "absolute"
217     elif enum == lldb.eSymbolTypeCode:
218         return "code"
219     elif enum == lldb.eSymbolTypeData:
220         return "data"
221     elif enum == lldb.eSymbolTypeTrampoline:
222         return "trampoline"
223     elif enum == lldb.eSymbolTypeRuntime:
224         return "runtime"
225     elif enum == lldb.eSymbolTypeException:
226         return "exception"
227     elif enum == lldb.eSymbolTypeSourceFile:
228         return "sourcefile"
229     elif enum == lldb.eSymbolTypeHeaderFile:
230         return "headerfile"
231     elif enum == lldb.eSymbolTypeObjectFile:
232         return "objectfile"
233     elif enum == lldb.eSymbolTypeCommonBlock:
234         return "commonblock"
235     elif enum == lldb.eSymbolTypeBlock:
236         return "block"
237     elif enum == lldb.eSymbolTypeLocal:
238         return "local"
239     elif enum == lldb.eSymbolTypeParam:
240         return "param"
241     elif enum == lldb.eSymbolTypeVariable:
242         return "variable"
243     elif enum == lldb.eSymbolTypeVariableType:
244         return "variabletype"
245     elif enum == lldb.eSymbolTypeLineEntry:
246         return "lineentry"
247     elif enum == lldb.eSymbolTypeLineHeader:
248         return "lineheader"
249     elif enum == lldb.eSymbolTypeScopeBegin:
250         return "scopebegin"
251     elif enum == lldb.eSymbolTypeScopeEnd:
252         return "scopeend"
253     elif enum == lldb.eSymbolTypeAdditional:
254         return "additional"
255     elif enum == lldb.eSymbolTypeCompiler:
256         return "compiler"
257     elif enum == lldb.eSymbolTypeInstrumentation:
258         return "instrumentation"
259     elif enum == lldb.eSymbolTypeUndefined:
260         return "undefined"
261
262
263 def value_type_to_str(enum):
264     """Returns the valueType string given an enum."""
265     if enum == lldb.eValueTypeInvalid:
266         return "invalid"
267     elif enum == lldb.eValueTypeVariableGlobal:
268         return "global_variable"
269     elif enum == lldb.eValueTypeVariableStatic:
270         return "static_variable"
271     elif enum == lldb.eValueTypeVariableArgument:
272         return "argument_variable"
273     elif enum == lldb.eValueTypeVariableLocal:
274         return "local_variable"
275     elif enum == lldb.eValueTypeRegister:
276         return "register"
277     elif enum == lldb.eValueTypeRegisterSet:
278         return "register_set"
279     elif enum == lldb.eValueTypeConstResult:
280         return "constant_result"
281     else:
282         raise Exception("Unknown ValueType enum")
283
284
285 # ==================================================
286 # Get stopped threads due to each stop reason.
287 # ==================================================
288
289 def sort_stopped_threads(process,
290                          breakpoint_threads=None,
291                          crashed_threads=None,
292                          watchpoint_threads=None,
293                          signal_threads=None,
294                          exiting_threads=None,
295                          other_threads=None):
296     """ Fills array *_threads with threads stopped for the corresponding stop
297         reason.
298     """
299     for lst in [breakpoint_threads,
300                 watchpoint_threads,
301                 signal_threads,
302                 exiting_threads,
303                 other_threads]:
304         if lst is not None:
305             lst[:] = []
306
307     for thread in process:
308         dispatched = False
309         for (reason, list) in [(lldb.eStopReasonBreakpoint, breakpoint_threads),
310                                (lldb.eStopReasonException, crashed_threads),
311                                (lldb.eStopReasonWatchpoint, watchpoint_threads),
312                                (lldb.eStopReasonSignal, signal_threads),
313                                (lldb.eStopReasonThreadExiting, exiting_threads),
314                                (None, other_threads)]:
315             if not dispatched and list is not None:
316                 if thread.GetStopReason() == reason or reason is None:
317                     list.append(thread)
318                     dispatched = True
319
320 # ==================================================
321 # Utility functions for setting breakpoints
322 # ==================================================
323
324
325 def run_break_set_by_file_and_line(
326         test,
327         file_name,
328         line_number,
329         extra_options=None,
330         num_expected_locations=1,
331         loc_exact=False,
332         module_name=None):
333     """Set a breakpoint by file and line, returning the breakpoint number.
334
335     If extra_options is not None, then we append it to the breakpoint set command.
336
337     If num_expected_locations is -1 we check that we got AT LEAST one location, otherwise we check that num_expected_locations equals the number of locations.
338
339     If loc_exact is true, we check that there is one location, and that location must be at the input file and line number."""
340
341     if file_name is None:
342         command = 'breakpoint set -l %d' % (line_number)
343     else:
344         command = 'breakpoint set -f "%s" -l %d' % (file_name, line_number)
345
346     if module_name:
347         command += " --shlib '%s'" % (module_name)
348
349     if extra_options:
350         command += " " + extra_options
351
352     break_results = run_break_set_command(test, command)
353
354     if num_expected_locations == 1 and loc_exact:
355         check_breakpoint_result(
356             test,
357             break_results,
358             num_locations=num_expected_locations,
359             file_name=file_name,
360             line_number=line_number,
361             module_name=module_name)
362     else:
363         check_breakpoint_result(
364             test,
365             break_results,
366             num_locations=num_expected_locations)
367
368     return get_bpno_from_match(break_results)
369
370
371 def run_break_set_by_symbol(
372         test,
373         symbol,
374         extra_options=None,
375         num_expected_locations=-1,
376         sym_exact=False,
377         module_name=None):
378     """Set a breakpoint by symbol name.  Common options are the same as run_break_set_by_file_and_line.
379
380     If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match."""
381     command = 'breakpoint set -n "%s"' % (symbol)
382
383     if module_name:
384         command += " --shlib '%s'" % (module_name)
385
386     if extra_options:
387         command += " " + extra_options
388
389     break_results = run_break_set_command(test, command)
390
391     if num_expected_locations == 1 and sym_exact:
392         check_breakpoint_result(
393             test,
394             break_results,
395             num_locations=num_expected_locations,
396             symbol_name=symbol,
397             module_name=module_name)
398     else:
399         check_breakpoint_result(
400             test,
401             break_results,
402             num_locations=num_expected_locations)
403
404     return get_bpno_from_match(break_results)
405
406
407 def run_break_set_by_selector(
408         test,
409         selector,
410         extra_options=None,
411         num_expected_locations=-1,
412         module_name=None):
413     """Set a breakpoint by selector.  Common options are the same as run_break_set_by_file_and_line."""
414
415     command = 'breakpoint set -S "%s"' % (selector)
416
417     if module_name:
418         command += ' --shlib "%s"' % (module_name)
419
420     if extra_options:
421         command += " " + extra_options
422
423     break_results = run_break_set_command(test, command)
424
425     if num_expected_locations == 1:
426         check_breakpoint_result(
427             test,
428             break_results,
429             num_locations=num_expected_locations,
430             symbol_name=selector,
431             symbol_match_exact=False,
432             module_name=module_name)
433     else:
434         check_breakpoint_result(
435             test,
436             break_results,
437             num_locations=num_expected_locations)
438
439     return get_bpno_from_match(break_results)
440
441
442 def run_break_set_by_regexp(
443         test,
444         regexp,
445         extra_options=None,
446         num_expected_locations=-1):
447     """Set a breakpoint by regular expression match on symbol name.  Common options are the same as run_break_set_by_file_and_line."""
448
449     command = 'breakpoint set -r "%s"' % (regexp)
450     if extra_options:
451         command += " " + extra_options
452
453     break_results = run_break_set_command(test, command)
454
455     check_breakpoint_result(
456         test,
457         break_results,
458         num_locations=num_expected_locations)
459
460     return get_bpno_from_match(break_results)
461
462
463 def run_break_set_by_source_regexp(
464         test,
465         regexp,
466         extra_options=None,
467         num_expected_locations=-1):
468     """Set a breakpoint by source regular expression.  Common options are the same as run_break_set_by_file_and_line."""
469     command = 'breakpoint set -p "%s"' % (regexp)
470     if extra_options:
471         command += " " + extra_options
472
473     break_results = run_break_set_command(test, command)
474
475     check_breakpoint_result(
476         test,
477         break_results,
478         num_locations=num_expected_locations)
479
480     return get_bpno_from_match(break_results)
481
482
483 def run_break_set_command(test, command):
484     """Run the command passed in - it must be some break set variant - and analyze the result.
485     Returns a dictionary of information gleaned from the command-line results.
486     Will assert if the breakpoint setting fails altogether.
487
488     Dictionary will contain:
489         bpno          - breakpoint of the newly created breakpoint, -1 on error.
490         num_locations - number of locations set for the breakpoint.
491
492     If there is only one location, the dictionary MAY contain:
493         file          - source file name
494         line_no       - source line number
495         symbol        - symbol name
496         inline_symbol - inlined symbol name
497         offset        - offset from the original symbol
498         module        - module
499         address       - address at which the breakpoint was set."""
500
501     patterns = [
502         r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$",
503         r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.",
504         r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>[+\-]{0,1}[^+]+)( \+ (?P<offset>[0-9]+)){0,1}( \[inlined\] (?P<inline_symbol>.*)){0,1} at (?P<file>[^:]+):(?P<line_no>[0-9]+), address = (?P<address>0x[0-9a-fA-F]+)$",
505         r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>.*)( \+ (?P<offset>[0-9]+)){0,1}, address = (?P<address>0x[0-9a-fA-F]+)$"]
506     match_object = test.match(command, patterns)
507     break_results = match_object.groupdict()
508
509     # We always insert the breakpoint number, setting it to -1 if we couldn't find it
510     # Also, make sure it gets stored as an integer.
511     if not 'bpno' in break_results:
512         break_results['bpno'] = -1
513     else:
514         break_results['bpno'] = int(break_results['bpno'])
515
516     # We always insert the number of locations
517     # If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1...
518     # We also make sure it is an integer.
519
520     if not 'num_locations' in break_results:
521         num_locations = 1
522     else:
523         num_locations = break_results['num_locations']
524         if num_locations == 'no':
525             num_locations = 0
526         else:
527             num_locations = int(break_results['num_locations'])
528
529     break_results['num_locations'] = num_locations
530
531     if 'line_no' in break_results:
532         break_results['line_no'] = int(break_results['line_no'])
533
534     return break_results
535
536
537 def get_bpno_from_match(break_results):
538     return int(break_results['bpno'])
539
540
541 def check_breakpoint_result(
542         test,
543         break_results,
544         file_name=None,
545         line_number=-1,
546         symbol_name=None,
547         symbol_match_exact=True,
548         module_name=None,
549         offset=-1,
550         num_locations=-1):
551
552     out_num_locations = break_results['num_locations']
553
554     if num_locations == -1:
555         test.assertTrue(out_num_locations > 0,
556                         "Expecting one or more locations, got none.")
557     else:
558         test.assertTrue(
559             num_locations == out_num_locations,
560             "Expecting %d locations, got %d." %
561             (num_locations,
562              out_num_locations))
563
564     if file_name:
565         out_file_name = ""
566         if 'file' in break_results:
567             out_file_name = break_results['file']
568         test.assertTrue(
569             file_name == out_file_name,
570             "Breakpoint file name '%s' doesn't match resultant name '%s'." %
571             (file_name,
572              out_file_name))
573
574     if line_number != -1:
575         out_line_number = -1
576         if 'line_no' in break_results:
577             out_line_number = break_results['line_no']
578
579         test.assertTrue(
580             line_number == out_line_number,
581             "Breakpoint line number %s doesn't match resultant line %s." %
582             (line_number,
583              out_line_number))
584
585     if symbol_name:
586         out_symbol_name = ""
587         # Look first for the inlined symbol name, otherwise use the symbol
588         # name:
589         if 'inline_symbol' in break_results and break_results['inline_symbol']:
590             out_symbol_name = break_results['inline_symbol']
591         elif 'symbol' in break_results:
592             out_symbol_name = break_results['symbol']
593
594         if symbol_match_exact:
595             test.assertTrue(
596                 symbol_name == out_symbol_name,
597                 "Symbol name '%s' doesn't match resultant symbol '%s'." %
598                 (symbol_name,
599                  out_symbol_name))
600         else:
601             test.assertTrue(
602                 out_symbol_name.find(symbol_name) != -
603                 1,
604                 "Symbol name '%s' isn't in resultant symbol '%s'." %
605                 (symbol_name,
606                  out_symbol_name))
607
608     if module_name:
609         out_module_name = None
610         if 'module' in break_results:
611             out_module_name = break_results['module']
612
613         test.assertTrue(
614             module_name.find(out_module_name) != -
615             1,
616             "Symbol module name '%s' isn't in expected module name '%s'." %
617             (out_module_name,
618              module_name))
619
620 # ==================================================
621 # Utility functions related to Threads and Processes
622 # ==================================================
623
624
625 def get_stopped_threads(process, reason):
626     """Returns the thread(s) with the specified stop reason in a list.
627
628     The list can be empty if no such thread exists.
629     """
630     threads = []
631     for t in process:
632         if t.GetStopReason() == reason:
633             threads.append(t)
634     return threads
635
636
637 def get_stopped_thread(process, reason):
638     """A convenience function which returns the first thread with the given stop
639     reason or None.
640
641     Example usages:
642
643     1. Get the stopped thread due to a breakpoint condition
644
645     ...
646         from lldbutil import get_stopped_thread
647         thread = get_stopped_thread(process, lldb.eStopReasonPlanComplete)
648         self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition")
649     ...
650
651     2. Get the thread stopped due to a breakpoint
652
653     ...
654         from lldbutil import get_stopped_thread
655         thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
656         self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint")
657     ...
658
659     """
660     threads = get_stopped_threads(process, reason)
661     if len(threads) == 0:
662         return None
663     return threads[0]
664
665
666 def get_threads_stopped_at_breakpoint_id(process, bpid):
667     """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
668     stopped_threads = []
669     threads = []
670
671     stopped_threads = get_stopped_threads(process, lldb.eStopReasonBreakpoint)
672
673     if len(stopped_threads) == 0:
674         return threads
675
676     for thread in stopped_threads:
677         # Make sure we've hit our breakpoint...
678         break_id = thread.GetStopReasonDataAtIndex(0)
679         if break_id == bpid:
680             threads.append(thread)
681
682     return threads
683
684
685 def get_threads_stopped_at_breakpoint(process, bkpt):
686     return get_threads_stopped_at_breakpoint_id(process, bkpt.GetID())
687
688
689 def get_one_thread_stopped_at_breakpoint_id(
690         process, bpid, require_exactly_one=True):
691     threads = get_threads_stopped_at_breakpoint_id(process, bpid)
692     if len(threads) == 0:
693         return None
694     if require_exactly_one and len(threads) != 1:
695         return None
696
697     return threads[0]
698
699
700 def get_one_thread_stopped_at_breakpoint(
701         process, bkpt, require_exactly_one=True):
702     return get_one_thread_stopped_at_breakpoint_id(
703         process, bkpt.GetID(), require_exactly_one)
704
705
706 def is_thread_crashed(test, thread):
707     """In the test suite we dereference a null pointer to simulate a crash. The way this is
708     reported depends on the platform."""
709     if test.platformIsDarwin():
710         return thread.GetStopReason(
711         ) == lldb.eStopReasonException and "EXC_BAD_ACCESS" in thread.GetStopDescription(100)
712     elif test.getPlatform() == "linux":
713         return thread.GetStopReason() == lldb.eStopReasonSignal and thread.GetStopReasonDataAtIndex(
714             0) == thread.GetProcess().GetUnixSignals().GetSignalNumberFromName("SIGSEGV")
715     else:
716         return "invalid address" in thread.GetStopDescription(100)
717
718
719 def get_crashed_threads(test, process):
720     threads = []
721     if process.GetState() != lldb.eStateStopped:
722         return threads
723     for thread in process:
724         if is_thread_crashed(test, thread):
725             threads.append(thread)
726     return threads
727
728
729 def continue_to_breakpoint(process, bkpt):
730     """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
731     process.Continue()
732     if process.GetState() != lldb.eStateStopped:
733         return None
734     else:
735         return get_threads_stopped_at_breakpoint(process, bkpt)
736
737
738 def get_caller_symbol(thread):
739     """
740     Returns the symbol name for the call site of the leaf function.
741     """
742     depth = thread.GetNumFrames()
743     if depth <= 1:
744         return None
745     caller = thread.GetFrameAtIndex(1).GetSymbol()
746     if caller:
747         return caller.GetName()
748     else:
749         return None
750
751
752 def get_function_names(thread):
753     """
754     Returns a sequence of function names from the stack frames of this thread.
755     """
756     def GetFuncName(i):
757         return thread.GetFrameAtIndex(i).GetFunctionName()
758
759     return list(map(GetFuncName, list(range(thread.GetNumFrames()))))
760
761
762 def get_symbol_names(thread):
763     """
764     Returns a sequence of symbols for this thread.
765     """
766     def GetSymbol(i):
767         return thread.GetFrameAtIndex(i).GetSymbol().GetName()
768
769     return list(map(GetSymbol, list(range(thread.GetNumFrames()))))
770
771
772 def get_pc_addresses(thread):
773     """
774     Returns a sequence of pc addresses for this thread.
775     """
776     def GetPCAddress(i):
777         return thread.GetFrameAtIndex(i).GetPCAddress()
778
779     return list(map(GetPCAddress, list(range(thread.GetNumFrames()))))
780
781
782 def get_filenames(thread):
783     """
784     Returns a sequence of file names from the stack frames of this thread.
785     """
786     def GetFilename(i):
787         return thread.GetFrameAtIndex(
788             i).GetLineEntry().GetFileSpec().GetFilename()
789
790     return list(map(GetFilename, list(range(thread.GetNumFrames()))))
791
792
793 def get_line_numbers(thread):
794     """
795     Returns a sequence of line numbers from the stack frames of this thread.
796     """
797     def GetLineNumber(i):
798         return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
799
800     return list(map(GetLineNumber, list(range(thread.GetNumFrames()))))
801
802
803 def get_module_names(thread):
804     """
805     Returns a sequence of module names from the stack frames of this thread.
806     """
807     def GetModuleName(i):
808         return thread.GetFrameAtIndex(
809             i).GetModule().GetFileSpec().GetFilename()
810
811     return list(map(GetModuleName, list(range(thread.GetNumFrames()))))
812
813
814 def get_stack_frames(thread):
815     """
816     Returns a sequence of stack frames for this thread.
817     """
818     def GetStackFrame(i):
819         return thread.GetFrameAtIndex(i)
820
821     return list(map(GetStackFrame, list(range(thread.GetNumFrames()))))
822
823
824 def print_stacktrace(thread, string_buffer=False):
825     """Prints a simple stack trace of this thread."""
826
827     output = SixStringIO() if string_buffer else sys.stdout
828     target = thread.GetProcess().GetTarget()
829
830     depth = thread.GetNumFrames()
831
832     mods = get_module_names(thread)
833     funcs = get_function_names(thread)
834     symbols = get_symbol_names(thread)
835     files = get_filenames(thread)
836     lines = get_line_numbers(thread)
837     addrs = get_pc_addresses(thread)
838
839     if thread.GetStopReason() != lldb.eStopReasonInvalid:
840         desc = "stop reason=" + stop_reason_to_str(thread.GetStopReason())
841     else:
842         desc = ""
843     print(
844         "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
845             thread.GetThreadID(),
846             thread.GetName(),
847             thread.GetQueueName()) + desc,
848         file=output)
849
850     for i in range(depth):
851         frame = thread.GetFrameAtIndex(i)
852         function = frame.GetFunction()
853
854         load_addr = addrs[i].GetLoadAddress(target)
855         if not function:
856             file_addr = addrs[i].GetFileAddress()
857             start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress()
858             symbol_offset = file_addr - start_addr
859             print(
860                 "  frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format(
861                     num=i,
862                     addr=load_addr,
863                     mod=mods[i],
864                     symbol=symbols[i],
865                     offset=symbol_offset),
866                 file=output)
867         else:
868             print(
869                 "  frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format(
870                     num=i,
871                     addr=load_addr,
872                     mod=mods[i],
873                     func='%s [inlined]' %
874                     funcs[i] if frame.IsInlined() else funcs[i],
875                     file=files[i],
876                     line=lines[i],
877                     args=get_args_as_string(
878                         frame,
879                         showFuncName=False) if not frame.IsInlined() else '()'),
880                 file=output)
881
882     if string_buffer:
883         return output.getvalue()
884
885
886 def print_stacktraces(process, string_buffer=False):
887     """Prints the stack traces of all the threads."""
888
889     output = SixStringIO() if string_buffer else sys.stdout
890
891     print("Stack traces for " + str(process), file=output)
892
893     for thread in process:
894         print(print_stacktrace(thread, string_buffer=True), file=output)
895
896     if string_buffer:
897         return output.getvalue()
898
899
900 def expect_state_changes(test, listener, process, states, timeout=5):
901     """Listens for state changed events on the listener and makes sure they match what we
902     expect. Stop-and-restart events (where GetRestartedFromEvent() returns true) are ignored."""
903
904     for expected_state in states:
905         def get_next_event():
906             event = lldb.SBEvent()
907             if not listener.WaitForEventForBroadcasterWithType(
908                     timeout,
909                     process.GetBroadcaster(),
910                     lldb.SBProcess.eBroadcastBitStateChanged,
911                     event):
912                 test.fail(
913                     "Timed out while waiting for a transition to state %s" %
914                     lldb.SBDebugger.StateAsCString(expected_state))
915             return event
916
917         event = get_next_event()
918         while (lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateStopped and
919                 lldb.SBProcess.GetRestartedFromEvent(event)):
920             # Ignore restarted event and the subsequent running event.
921             event = get_next_event()
922             test.assertEqual(
923                 lldb.SBProcess.GetStateFromEvent(event),
924                 lldb.eStateRunning,
925                 "Restarted event followed by a running event")
926             event = get_next_event()
927
928         test.assertEqual(
929             lldb.SBProcess.GetStateFromEvent(event),
930             expected_state)
931
932 # ===================================
933 # Utility functions related to Frames
934 # ===================================
935
936
937 def get_parent_frame(frame):
938     """
939     Returns the parent frame of the input frame object; None if not available.
940     """
941     thread = frame.GetThread()
942     parent_found = False
943     for f in thread:
944         if parent_found:
945             return f
946         if f.GetFrameID() == frame.GetFrameID():
947             parent_found = True
948
949     # If we reach here, no parent has been found, return None.
950     return None
951
952
953 def get_args_as_string(frame, showFuncName=True):
954     """
955     Returns the args of the input frame object as a string.
956     """
957     # arguments     => True
958     # locals        => False
959     # statics       => False
960     # in_scope_only => True
961     vars = frame.GetVariables(True, False, False, True)  # type of SBValueList
962     args = []  # list of strings
963     for var in vars:
964         args.append("(%s)%s=%s" % (var.GetTypeName(),
965                                    var.GetName(),
966                                    var.GetValue()))
967     if frame.GetFunction():
968         name = frame.GetFunction().GetName()
969     elif frame.GetSymbol():
970         name = frame.GetSymbol().GetName()
971     else:
972         name = ""
973     if showFuncName:
974         return "%s(%s)" % (name, ", ".join(args))
975     else:
976         return "(%s)" % (", ".join(args))
977
978
979 def print_registers(frame, string_buffer=False):
980     """Prints all the register sets of the frame."""
981
982     output = SixStringIO() if string_buffer else sys.stdout
983
984     print("Register sets for " + str(frame), file=output)
985
986     registerSet = frame.GetRegisters()  # Return type of SBValueList.
987     print("Frame registers (size of register set = %d):" %
988           registerSet.GetSize(), file=output)
989     for value in registerSet:
990         #print(value, file=output)
991         print("%s (number of children = %d):" %
992               (value.GetName(), value.GetNumChildren()), file=output)
993         for child in value:
994             print(
995                 "Name: %s, Value: %s" %
996                 (child.GetName(),
997                  child.GetValue()),
998                 file=output)
999
1000     if string_buffer:
1001         return output.getvalue()
1002
1003
1004 def get_registers(frame, kind):
1005     """Returns the registers given the frame and the kind of registers desired.
1006
1007     Returns None if there's no such kind.
1008     """
1009     registerSet = frame.GetRegisters()  # Return type of SBValueList.
1010     for value in registerSet:
1011         if kind.lower() in value.GetName().lower():
1012             return value
1013
1014     return None
1015
1016
1017 def get_GPRs(frame):
1018     """Returns the general purpose registers of the frame as an SBValue.
1019
1020     The returned SBValue object is iterable.  An example:
1021         ...
1022         from lldbutil import get_GPRs
1023         regs = get_GPRs(frame)
1024         for reg in regs:
1025             print("%s => %s" % (reg.GetName(), reg.GetValue()))
1026         ...
1027     """
1028     return get_registers(frame, "general purpose")
1029
1030
1031 def get_FPRs(frame):
1032     """Returns the floating point registers of the frame as an SBValue.
1033
1034     The returned SBValue object is iterable.  An example:
1035         ...
1036         from lldbutil import get_FPRs
1037         regs = get_FPRs(frame)
1038         for reg in regs:
1039             print("%s => %s" % (reg.GetName(), reg.GetValue()))
1040         ...
1041     """
1042     return get_registers(frame, "floating point")
1043
1044
1045 def get_ESRs(frame):
1046     """Returns the exception state registers of the frame as an SBValue.
1047
1048     The returned SBValue object is iterable.  An example:
1049         ...
1050         from lldbutil import get_ESRs
1051         regs = get_ESRs(frame)
1052         for reg in regs:
1053             print("%s => %s" % (reg.GetName(), reg.GetValue()))
1054         ...
1055     """
1056     return get_registers(frame, "exception state")
1057
1058 # ======================================
1059 # Utility classes/functions for SBValues
1060 # ======================================
1061
1062
1063 class BasicFormatter(object):
1064     """The basic formatter inspects the value object and prints the value."""
1065
1066     def format(self, value, buffer=None, indent=0):
1067         if not buffer:
1068             output = SixStringIO()
1069         else:
1070             output = buffer
1071         # If there is a summary, it suffices.
1072         val = value.GetSummary()
1073         # Otherwise, get the value.
1074         if val is None:
1075             val = value.GetValue()
1076         if val is None and value.GetNumChildren() > 0:
1077             val = "%s (location)" % value.GetLocation()
1078         print("{indentation}({type}) {name} = {value}".format(
1079             indentation=' ' * indent,
1080             type=value.GetTypeName(),
1081             name=value.GetName(),
1082             value=val), file=output)
1083         return output.getvalue()
1084
1085
1086 class ChildVisitingFormatter(BasicFormatter):
1087     """The child visiting formatter prints the value and its immediate children.
1088
1089     The constructor takes a keyword arg: indent_child, which defaults to 2.
1090     """
1091
1092     def __init__(self, indent_child=2):
1093         """Default indentation of 2 SPC's for the children."""
1094         self.cindent = indent_child
1095
1096     def format(self, value, buffer=None):
1097         if not buffer:
1098             output = SixStringIO()
1099         else:
1100             output = buffer
1101
1102         BasicFormatter.format(self, value, buffer=output)
1103         for child in value:
1104             BasicFormatter.format(
1105                 self, child, buffer=output, indent=self.cindent)
1106
1107         return output.getvalue()
1108
1109
1110 class RecursiveDecentFormatter(BasicFormatter):
1111     """The recursive decent formatter prints the value and the decendents.
1112
1113     The constructor takes two keyword args: indent_level, which defaults to 0,
1114     and indent_child, which defaults to 2.  The current indentation level is
1115     determined by indent_level, while the immediate children has an additional
1116     indentation by inden_child.
1117     """
1118
1119     def __init__(self, indent_level=0, indent_child=2):
1120         self.lindent = indent_level
1121         self.cindent = indent_child
1122
1123     def format(self, value, buffer=None):
1124         if not buffer:
1125             output = SixStringIO()
1126         else:
1127             output = buffer
1128
1129         BasicFormatter.format(self, value, buffer=output, indent=self.lindent)
1130         new_indent = self.lindent + self.cindent
1131         for child in value:
1132             if child.GetSummary() is not None:
1133                 BasicFormatter.format(
1134                     self, child, buffer=output, indent=new_indent)
1135             else:
1136                 if child.GetNumChildren() > 0:
1137                     rdf = RecursiveDecentFormatter(indent_level=new_indent)
1138                     rdf.format(child, buffer=output)
1139                 else:
1140                     BasicFormatter.format(
1141                         self, child, buffer=output, indent=new_indent)
1142
1143         return output.getvalue()
1144
1145 # ===========================================================
1146 # Utility functions for path manipulation on remote platforms
1147 # ===========================================================
1148
1149
1150 def join_remote_paths(*paths):
1151     # TODO: update with actual platform name for remote windows once it exists
1152     if lldb.remote_platform.GetName() == 'remote-windows':
1153         return os.path.join(*paths).replace(os.path.sep, '\\')
1154     return os.path.join(*paths).replace(os.path.sep, '/')
1155
1156
1157 def append_to_process_working_directory(*paths):
1158     remote = lldb.remote_platform
1159     if remote:
1160         return join_remote_paths(remote.GetWorkingDirectory(), *paths)
1161     return os.path.join(os.getcwd(), *paths)
1162
1163 # ==================================================
1164 # Utility functions to get the correct signal number
1165 # ==================================================
1166
1167 import signal
1168
1169
1170 def get_signal_number(signal_name):
1171     platform = lldb.remote_platform
1172     if platform and platform.IsValid():
1173         signals = platform.GetUnixSignals()
1174         if signals.IsValid():
1175             signal_number = signals.GetSignalNumberFromName(signal_name)
1176             if signal_number > 0:
1177                 return signal_number
1178     # No remote platform; fall back to using local python signals.
1179     return getattr(signal, signal_name)
1180
1181
1182 class PrintableRegex(object):
1183
1184     def __init__(self, text):
1185         self.regex = re.compile(text)
1186         self.text = text
1187
1188     def match(self, str):
1189         return self.regex.match(str)
1190
1191     def __str__(self):
1192         return "%s" % (self.text)
1193
1194     def __repr__(self):
1195         return "re.compile(%s) -> %s" % (self.text, self.regex)
1196
1197
1198 def skip_if_callable(test, mycallable, reason):
1199     if six.callable(mycallable):
1200         if mycallable(test):
1201             test.skipTest(reason)
1202             return True
1203     return False
1204
1205
1206 def skip_if_library_missing(test, target, library):
1207     def find_library(target, library):
1208         for module in target.modules:
1209             filename = module.file.GetFilename()
1210             if isinstance(library, str):
1211                 if library == filename:
1212                     return False
1213             elif hasattr(library, 'match'):
1214                 if library.match(filename):
1215                     return False
1216         return True
1217
1218     def find_library_callable(test):
1219         return find_library(target, library)
1220     return skip_if_callable(
1221         test,
1222         find_library_callable,
1223         "could not find library matching '%s' in target %s" %
1224         (library,
1225          target))
1226
1227
1228 def wait_for_file_on_target(testcase, file_path, max_attempts=6):
1229     for i in range(max_attempts):
1230         err, retcode, msg = testcase.run_platform_command("ls %s" % file_path)
1231         if err.Success() and retcode == 0:
1232             break
1233         if i < max_attempts:
1234             # Exponential backoff!
1235             import time
1236             time.sleep(pow(2, i) * 0.25)
1237     else:
1238         testcase.fail(
1239             "File %s not found even after %d attempts." %
1240             (file_path, max_attempts))
1241
1242     err, retcode, data = testcase.run_platform_command("cat %s" % (file_path))
1243
1244     testcase.assertTrue(
1245         err.Success() and retcode == 0, "Failed to read file %s: %s, retcode: %d" %
1246         (file_path, err.GetCString(), retcode))
1247     return data