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