1import lldb
2from intelpt_testcase import *
3from lldbsuite.test.lldbtest import *
4from lldbsuite.test import lldbutil
5from lldbsuite.test.decorators import *
6
7class TestTraceEvents(TraceIntelPTTestCaseBase):
8
9    @testSBAPIAndCommands
10    def testCPUEvents(self):
11      trace_description_file_path = os.path.join(self.getSourceDir(), "intelpt-multi-core-trace", "trace_missing_threads.json")
12      self.traceLoad(traceDescriptionFilePath=trace_description_file_path, substrs=["intel-pt"])
13
14      self.expect("thread trace dump instructions 3 -e --forward -c 5",
15        substrs=['''thread #3: tid = 3497496
16    0: (event) CPU core changed [new CPU=51]
17  m.out`foo() + 65 at multi_thread.cpp:12:21'''])
18
19      self.expect("thread trace dump instructions 3 -e --forward -c 5 -J",
20        substrs=['''{
21    "id": 0,
22    "event": "CPU core changed",
23    "cpuId": 51
24  }'''])
25
26    @testSBAPIAndCommands
27    def testPauseEvents(self):
28      '''
29        Everytime the target stops running on the CPU, a 'disabled' event will
30        be emitted, which is represented by the TraceCursor API as a 'paused'
31        event.
32      '''
33      self.expect("target create " +
34            os.path.join(self.getSourceDir(), "intelpt-trace-multi-file", "a.out"))
35      self.expect("b 12")
36      self.expect("r")
37      self.traceStartThread()
38      self.expect("n")
39      self.expect("n")
40      self.expect("si")
41      self.expect("si")
42      self.expect("si")
43      # We ensure that the paused events are printed correctly forward
44      self.expect("thread trace dump instructions -e -f",
45        patterns=[f'''thread #1: tid = .*
46  a.out`main \+ 23 at main.cpp:12
47    0: {ADDRESS_REGEX}    movl .*
48    1: \(event\) software disabled tracing
49    2: {ADDRESS_REGEX}    addl .*
50    3: {ADDRESS_REGEX}    movl .*
51    4: \(event\) software disabled tracing
52  a.out`main \+ 34 \[inlined\] inline_function\(\) at main.cpp:4
53    5: {ADDRESS_REGEX}    movl .*
54  a.out`main \+ 41 \[inlined\] inline_function\(\) \+ 7 at main.cpp:5
55    6: {ADDRESS_REGEX}    movl .*
56    7: {ADDRESS_REGEX}    addl .*
57    8: {ADDRESS_REGEX}    movl .*
58  a.out`main \+ 52 \[inlined\] inline_function\(\) \+ 18 at main.cpp:6
59    9: {ADDRESS_REGEX}    movl .*
60  a.out`main \+ 55 at main.cpp:14
61    10: {ADDRESS_REGEX}    movl .*
62    11: {ADDRESS_REGEX}    addl .*
63    12: {ADDRESS_REGEX}    movl .*
64    13: \(event\) software disabled tracing
65  a.out`main \+ 63 at main.cpp:16
66    14: {ADDRESS_REGEX}    callq  .* ; symbol stub for: foo\(\)
67    15: \(event\) software disabled tracing
68  a.out`symbol stub for: foo\(\)
69    16: {ADDRESS_REGEX}    jmpq'''])
70
71      # We ensure that the paused events are printed correctly backward
72      self.expect("thread trace dump instructions -e --id 16",
73        patterns=[f'''thread #1: tid = .*
74  a.out`symbol stub for: foo\(\)
75    16: {ADDRESS_REGEX}    jmpq .*
76    15: \(event\) software disabled tracing
77  a.out`main \+ 63 at main.cpp:16
78    14: {ADDRESS_REGEX}    callq  .* ; symbol stub for: foo\(\)
79    13: \(event\) software disabled tracing
80  a.out`main \+ 60 at main.cpp:14
81    12: {ADDRESS_REGEX}    movl .*
82    11: {ADDRESS_REGEX}    addl .*
83    10: {ADDRESS_REGEX}    movl .*
84  a.out`main \+ 52 \[inlined\] inline_function\(\) \+ 18 at main.cpp:6
85    9: {ADDRESS_REGEX}    movl .*
86  a.out`main \+ 49 \[inlined\] inline_function\(\) \+ 15 at main.cpp:5
87    8: {ADDRESS_REGEX}    movl .*
88    7: {ADDRESS_REGEX}    addl .*
89    6: {ADDRESS_REGEX}    movl .*
90  a.out`main \+ 34 \[inlined\] inline_function\(\) at main.cpp:4
91    5: {ADDRESS_REGEX}    movl .*
92    4: \(event\) software disabled tracing
93  a.out`main \+ 31 at main.cpp:12
94    3: {ADDRESS_REGEX}    movl .*
95    2: {ADDRESS_REGEX}    addl .*
96    1: \(event\) software disabled tracing
97    0: {ADDRESS_REGEX}    movl .*'''])
98