1fb19f11eSWalter Erquinigoimport lldb 2bf9f21a2SWalter Erquinigofrom intelpt_testcase import * 3fb19f11eSWalter Erquinigofrom lldbsuite.test.lldbtest import * 4fb19f11eSWalter Erquinigofrom lldbsuite.test import lldbutil 5fb19f11eSWalter Erquinigofrom lldbsuite.test.decorators import * 6fb19f11eSWalter Erquinigo 7fb19f11eSWalter Erquinigo 8*2238dcc3SJonas Devlieghereclass TestTraceStartStop(TraceIntelPTTestCaseBase): 9fb19f11eSWalter Erquinigo def expectGenericHelpMessageForStartCommand(self): 10*2238dcc3SJonas Devlieghere self.expect( 11*2238dcc3SJonas Devlieghere "help thread trace start", 12*2238dcc3SJonas Devlieghere substrs=["Syntax: thread trace start [<trace-options>]"], 13*2238dcc3SJonas Devlieghere ) 14fb19f11eSWalter Erquinigo 15bf9f21a2SWalter Erquinigo @testSBAPIAndCommands 16fb19f11eSWalter Erquinigo def testStartStopSessionFileThreads(self): 17fb19f11eSWalter Erquinigo # it should fail for processes from json session files 18*2238dcc3SJonas Devlieghere self.expect( 19*2238dcc3SJonas Devlieghere "trace load -v " 20*2238dcc3SJonas Devlieghere + os.path.join(self.getSourceDir(), "intelpt-trace", "trace.json") 21*2238dcc3SJonas Devlieghere ) 22fb19f11eSWalter Erquinigo 23fb19f11eSWalter Erquinigo # the help command should be the generic one, as it's not a live process 24fb19f11eSWalter Erquinigo self.expectGenericHelpMessageForStartCommand() 25fb19f11eSWalter Erquinigo 26bf9f21a2SWalter Erquinigo self.traceStartThread(error=True) 270b697561SWalter Erquinigo 28bf9f21a2SWalter Erquinigo self.traceStopThread(error=True) 29bf9f21a2SWalter Erquinigo 30bf9f21a2SWalter Erquinigo @testSBAPIAndCommands 310b697561SWalter Erquinigo def testStartWithNoProcess(self): 32bf9f21a2SWalter Erquinigo self.traceStartThread(error=True) 330b697561SWalter Erquinigo 34bf9f21a2SWalter Erquinigo @testSBAPIAndCommands 350b697561SWalter Erquinigo def testStartSessionWithWrongSize(self): 36*2238dcc3SJonas Devlieghere self.expect( 37*2238dcc3SJonas Devlieghere "file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out") 38*2238dcc3SJonas Devlieghere ) 390b697561SWalter Erquinigo self.expect("b main") 400b697561SWalter Erquinigo self.expect("r") 41bf9f21a2SWalter Erquinigo 42bf9f21a2SWalter Erquinigo self.traceStartThread( 43*2238dcc3SJonas Devlieghere error=True, 44*2238dcc3SJonas Devlieghere iptTraceSize=2000, 45*2238dcc3SJonas Devlieghere substrs=["The intel pt trace size must be a power of 2", "It was 2000"], 46*2238dcc3SJonas Devlieghere ) 47bf9f21a2SWalter Erquinigo 48bf9f21a2SWalter Erquinigo self.traceStartThread( 49*2238dcc3SJonas Devlieghere error=True, 50*2238dcc3SJonas Devlieghere iptTraceSize=5000, 51*2238dcc3SJonas Devlieghere substrs=["The intel pt trace size must be a power of 2", "It was 5000"], 52*2238dcc3SJonas Devlieghere ) 53bf9f21a2SWalter Erquinigo 54bf9f21a2SWalter Erquinigo self.traceStartThread( 55*2238dcc3SJonas Devlieghere error=True, 56*2238dcc3SJonas Devlieghere iptTraceSize=0, 57*2238dcc3SJonas Devlieghere substrs=["The intel pt trace size must be a power of 2", "It was 0"], 58*2238dcc3SJonas Devlieghere ) 59bf9f21a2SWalter Erquinigo 606a5355e8SWalter Erquinigo self.traceStartThread(iptTraceSize=1048576) 61bf9f21a2SWalter Erquinigo 62db73a52dSrnofenko @testSBAPIAndCommands 63db73a52dSrnofenko def testStartSessionWithSizeDeclarationInUnits(self): 64*2238dcc3SJonas Devlieghere self.expect( 65*2238dcc3SJonas Devlieghere "file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out") 66*2238dcc3SJonas Devlieghere ) 67db73a52dSrnofenko self.expect("b main") 68db73a52dSrnofenko self.expect("r") 69db73a52dSrnofenko 70db73a52dSrnofenko self.traceStartThread( 71*2238dcc3SJonas Devlieghere error=True, 72*2238dcc3SJonas Devlieghere iptTraceSize="abc", 73*2238dcc3SJonas Devlieghere substrs=["invalid bytes expression for 'abc'"], 74*2238dcc3SJonas Devlieghere ) 75db73a52dSrnofenko 76db73a52dSrnofenko self.traceStartThread( 77*2238dcc3SJonas Devlieghere error=True, 78*2238dcc3SJonas Devlieghere iptTraceSize="123.12", 79*2238dcc3SJonas Devlieghere substrs=["invalid bytes expression for '123.12'"], 80*2238dcc3SJonas Devlieghere ) 81db73a52dSrnofenko 82db73a52dSrnofenko self.traceStartThread( 83*2238dcc3SJonas Devlieghere error=True, iptTraceSize='""', substrs=["invalid bytes expression for ''"] 84*2238dcc3SJonas Devlieghere ) 85db73a52dSrnofenko 86db73a52dSrnofenko self.traceStartThread( 87*2238dcc3SJonas Devlieghere error=True, 88*2238dcc3SJonas Devlieghere iptTraceSize="2000B", 89*2238dcc3SJonas Devlieghere substrs=[ 90*2238dcc3SJonas Devlieghere "The intel pt trace size must be a power of 2 greater than or equal to 4096 (2^12) bytes. It was 2000" 91*2238dcc3SJonas Devlieghere ], 92*2238dcc3SJonas Devlieghere ) 93db73a52dSrnofenko 94db73a52dSrnofenko self.traceStartThread( 95*2238dcc3SJonas Devlieghere error=True, 96*2238dcc3SJonas Devlieghere iptTraceSize="3MB", 97*2238dcc3SJonas Devlieghere substrs=[ 98*2238dcc3SJonas Devlieghere "The intel pt trace size must be a power of 2 greater than or equal to 4096 (2^12) bytes. It was 3145728" 99*2238dcc3SJonas Devlieghere ], 100*2238dcc3SJonas Devlieghere ) 101db73a52dSrnofenko 102db73a52dSrnofenko self.traceStartThread( 103*2238dcc3SJonas Devlieghere error=True, 104*2238dcc3SJonas Devlieghere iptTraceSize="3MiB", 105*2238dcc3SJonas Devlieghere substrs=[ 106*2238dcc3SJonas Devlieghere "The intel pt trace size must be a power of 2 greater than or equal to 4096 (2^12) bytes. It was 3145728" 107*2238dcc3SJonas Devlieghere ], 108*2238dcc3SJonas Devlieghere ) 109db73a52dSrnofenko 110db73a52dSrnofenko self.traceStartThread( 111*2238dcc3SJonas Devlieghere error=True, 112*2238dcc3SJonas Devlieghere iptTraceSize="3mib", 113*2238dcc3SJonas Devlieghere substrs=[ 114*2238dcc3SJonas Devlieghere "The intel pt trace size must be a power of 2 greater than or equal to 4096 (2^12) bytes. It was 3145728" 115*2238dcc3SJonas Devlieghere ], 116*2238dcc3SJonas Devlieghere ) 117db73a52dSrnofenko 118db73a52dSrnofenko self.traceStartThread( 119*2238dcc3SJonas Devlieghere error=True, 120*2238dcc3SJonas Devlieghere iptTraceSize="3M", 121*2238dcc3SJonas Devlieghere substrs=[ 122*2238dcc3SJonas Devlieghere "The intel pt trace size must be a power of 2 greater than or equal to 4096 (2^12) bytes. It was 3145728" 123*2238dcc3SJonas Devlieghere ], 124*2238dcc3SJonas Devlieghere ) 125db73a52dSrnofenko 126db73a52dSrnofenko self.traceStartThread( 127*2238dcc3SJonas Devlieghere error=True, 128*2238dcc3SJonas Devlieghere iptTraceSize="3KB", 129*2238dcc3SJonas Devlieghere substrs=[ 130*2238dcc3SJonas Devlieghere "The intel pt trace size must be a power of 2 greater than or equal to 4096 (2^12) bytes. It was 3072" 131*2238dcc3SJonas Devlieghere ], 132*2238dcc3SJonas Devlieghere ) 133db73a52dSrnofenko 134db73a52dSrnofenko self.traceStartThread( 135*2238dcc3SJonas Devlieghere error=True, 136*2238dcc3SJonas Devlieghere iptTraceSize="3KiB", 137*2238dcc3SJonas Devlieghere substrs=[ 138*2238dcc3SJonas Devlieghere "The intel pt trace size must be a power of 2 greater than or equal to 4096 (2^12) bytes. It was 3072" 139*2238dcc3SJonas Devlieghere ], 140*2238dcc3SJonas Devlieghere ) 141db73a52dSrnofenko 142db73a52dSrnofenko self.traceStartThread( 143*2238dcc3SJonas Devlieghere error=True, 144*2238dcc3SJonas Devlieghere iptTraceSize="3K", 145*2238dcc3SJonas Devlieghere substrs=[ 146*2238dcc3SJonas Devlieghere "The intel pt trace size must be a power of 2 greater than or equal to 4096 (2^12) bytes. It was 3072" 147*2238dcc3SJonas Devlieghere ], 148*2238dcc3SJonas Devlieghere ) 149db73a52dSrnofenko 150db73a52dSrnofenko self.traceStartThread( 151*2238dcc3SJonas Devlieghere error=True, 152*2238dcc3SJonas Devlieghere iptTraceSize="3MS", 153*2238dcc3SJonas Devlieghere substrs=["invalid bytes expression for '3MS'"], 154*2238dcc3SJonas Devlieghere ) 155db73a52dSrnofenko 156db73a52dSrnofenko self.traceStartThread(iptTraceSize="1048576") 157db73a52dSrnofenko 158*2238dcc3SJonas Devlieghere @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"])) 159bf9f21a2SWalter Erquinigo def testSBAPIHelp(self): 160*2238dcc3SJonas Devlieghere self.expect( 161*2238dcc3SJonas Devlieghere "file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out") 162*2238dcc3SJonas Devlieghere ) 163bf9f21a2SWalter Erquinigo self.expect("b main") 164bf9f21a2SWalter Erquinigo self.expect("r") 165bf9f21a2SWalter Erquinigo 166bf9f21a2SWalter Erquinigo help = self.getTraceOrCreate().GetStartConfigurationHelp() 1676a5355e8SWalter Erquinigo self.assertIn("iptTraceSize", help) 168bf9f21a2SWalter Erquinigo self.assertIn("processBufferSizeLimit", help) 169bf9f21a2SWalter Erquinigo 170*2238dcc3SJonas Devlieghere @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"])) 171bf9f21a2SWalter Erquinigo def testStoppingAThread(self): 172*2238dcc3SJonas Devlieghere self.expect( 173*2238dcc3SJonas Devlieghere "file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out") 174*2238dcc3SJonas Devlieghere ) 175bf9f21a2SWalter Erquinigo self.expect("b main") 176bf9f21a2SWalter Erquinigo self.expect("r") 177bf9f21a2SWalter Erquinigo self.expect("thread trace start") 178bf9f21a2SWalter Erquinigo self.expect("n") 179*2238dcc3SJonas Devlieghere self.expect( 180*2238dcc3SJonas Devlieghere "thread trace dump instructions", 181*2238dcc3SJonas Devlieghere substrs=[ 182*2238dcc3SJonas Devlieghere """0x0000000000400511 movl $0x0, -0x4(%rbp) 183*2238dcc3SJonas Devlieghere no more data""" 184*2238dcc3SJonas Devlieghere ], 185*2238dcc3SJonas Devlieghere ) 186bf9f21a2SWalter Erquinigo # process stopping should stop the thread 187bf9f21a2SWalter Erquinigo self.expect("process trace stop") 188bf9f21a2SWalter Erquinigo self.expect("n") 189*2238dcc3SJonas Devlieghere self.expect( 190*2238dcc3SJonas Devlieghere "thread trace dump instructions", substrs=["not traced"], error=True 191*2238dcc3SJonas Devlieghere ) 1920b697561SWalter Erquinigo 193*2238dcc3SJonas Devlieghere @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"])) 194fb19f11eSWalter Erquinigo def testStartStopLiveThreads(self): 195fb19f11eSWalter Erquinigo # The help command should be the generic one if there's no process running 196fb19f11eSWalter Erquinigo self.expectGenericHelpMessageForStartCommand() 197fb19f11eSWalter Erquinigo 198*2238dcc3SJonas Devlieghere self.expect( 199*2238dcc3SJonas Devlieghere "thread trace start", error=True, substrs=["error: Process not available"] 200*2238dcc3SJonas Devlieghere ) 201fb19f11eSWalter Erquinigo 202*2238dcc3SJonas Devlieghere self.expect( 203*2238dcc3SJonas Devlieghere "file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out") 204*2238dcc3SJonas Devlieghere ) 205fb19f11eSWalter Erquinigo self.expect("b main") 206fb19f11eSWalter Erquinigo 207*2238dcc3SJonas Devlieghere self.expect( 208*2238dcc3SJonas Devlieghere "thread trace start", error=True, substrs=["error: Process not available"] 209*2238dcc3SJonas Devlieghere ) 210fb19f11eSWalter Erquinigo 211fb19f11eSWalter Erquinigo # The help command should be the generic one if there's still no process running 212fb19f11eSWalter Erquinigo self.expectGenericHelpMessageForStartCommand() 213fb19f11eSWalter Erquinigo 214fb19f11eSWalter Erquinigo self.expect("r") 215fb19f11eSWalter Erquinigo 2160b697561SWalter Erquinigo # This fails because "trace start" hasn't been called yet 217*2238dcc3SJonas Devlieghere self.expect( 218*2238dcc3SJonas Devlieghere "thread trace stop", 219*2238dcc3SJonas Devlieghere error=True, 220*2238dcc3SJonas Devlieghere substrs=["error: Process is not being traced"], 221*2238dcc3SJonas Devlieghere ) 2220b697561SWalter Erquinigo 223fb19f11eSWalter Erquinigo # the help command should be the intel-pt one now 224*2238dcc3SJonas Devlieghere self.expect( 225*2238dcc3SJonas Devlieghere "help thread trace start", 226*2238dcc3SJonas Devlieghere substrs=[ 227*2238dcc3SJonas Devlieghere "Start tracing one or more threads with intel-pt.", 228*2238dcc3SJonas Devlieghere "Syntax: thread trace start [<thread-index> <thread-index> ...] [<intel-pt-options>]", 229*2238dcc3SJonas Devlieghere ], 230*2238dcc3SJonas Devlieghere ) 231fb19f11eSWalter Erquinigo 2320b697561SWalter Erquinigo # We start tracing with a small buffer size 2330b697561SWalter Erquinigo self.expect("thread trace start 1 --size 4096") 234fb19f11eSWalter Erquinigo 2350b697561SWalter Erquinigo # We fail if we try to trace again 236*2238dcc3SJonas Devlieghere self.expect( 237*2238dcc3SJonas Devlieghere "thread trace start", 238*2238dcc3SJonas Devlieghere error=True, 239*2238dcc3SJonas Devlieghere substrs=["error: Thread ", "already traced"], 240*2238dcc3SJonas Devlieghere ) 241fb19f11eSWalter Erquinigo 2420b697561SWalter Erquinigo # We can reconstruct the single instruction executed in the first line 2430b697561SWalter Erquinigo self.expect("n") 244*2238dcc3SJonas Devlieghere self.expect( 245*2238dcc3SJonas Devlieghere "thread trace dump instructions -f", 246*2238dcc3SJonas Devlieghere patterns=[ 247*2238dcc3SJonas Devlieghere f"""thread #1: tid = .* 2480b697561SWalter Erquinigo a.out`main \+ 4 at main.cpp:2 249*2238dcc3SJonas Devlieghere 2: {ADDRESS_REGEX} movl""" 250*2238dcc3SJonas Devlieghere ], 251*2238dcc3SJonas Devlieghere ) 2520b697561SWalter Erquinigo 2530b697561SWalter Erquinigo # We can reconstruct the instructions up to the second line 2540b697561SWalter Erquinigo self.expect("n") 255*2238dcc3SJonas Devlieghere self.expect( 256*2238dcc3SJonas Devlieghere "thread trace dump instructions -f", 257*2238dcc3SJonas Devlieghere patterns=[ 258*2238dcc3SJonas Devlieghere f"""thread #1: tid = .* 2590b697561SWalter Erquinigo a.out`main \+ 4 at main.cpp:2 2602098e2f4SWalter Erquinigo 2: {ADDRESS_REGEX} movl .* 2610b697561SWalter Erquinigo a.out`main \+ 11 at main.cpp:4 2622098e2f4SWalter Erquinigo 4: {ADDRESS_REGEX} movl .* 2632098e2f4SWalter Erquinigo 6: {ADDRESS_REGEX} jmp .* ; <\+28> at main.cpp:4 2642098e2f4SWalter Erquinigo 8: {ADDRESS_REGEX} cmpl .* 265*2238dcc3SJonas Devlieghere 10: {ADDRESS_REGEX} jle .* ; <\+20> at main.cpp:5""" 266*2238dcc3SJonas Devlieghere ], 267*2238dcc3SJonas Devlieghere ) 2680b697561SWalter Erquinigo 269*2238dcc3SJonas Devlieghere self.expect( 270*2238dcc3SJonas Devlieghere "thread trace dump instructions", 271*2238dcc3SJonas Devlieghere patterns=[ 272*2238dcc3SJonas Devlieghere f"""thread #1: tid = .* 273b0aa7076SWalter Erquinigo a.out`main \+ 32 at main.cpp:4 2742098e2f4SWalter Erquinigo 10: {ADDRESS_REGEX} jle .* ; <\+20> at main.cpp:5 2752098e2f4SWalter Erquinigo 8: {ADDRESS_REGEX} cmpl .* 2762098e2f4SWalter Erquinigo 6: {ADDRESS_REGEX} jmp .* ; <\+28> at main.cpp:4 2772098e2f4SWalter Erquinigo 4: {ADDRESS_REGEX} movl .* 278b0aa7076SWalter Erquinigo a.out`main \+ 4 at main.cpp:2 279*2238dcc3SJonas Devlieghere 2: {ADDRESS_REGEX} movl .* """ 280*2238dcc3SJonas Devlieghere ], 281*2238dcc3SJonas Devlieghere ) 282b0aa7076SWalter Erquinigo 2830b697561SWalter Erquinigo # We stop tracing 2840b697561SWalter Erquinigo self.expect("thread trace stop") 2850b697561SWalter Erquinigo 2860b697561SWalter Erquinigo # We can't stop twice 287*2238dcc3SJonas Devlieghere self.expect( 288*2238dcc3SJonas Devlieghere "thread trace stop", 289*2238dcc3SJonas Devlieghere error=True, 290*2238dcc3SJonas Devlieghere substrs=["error: Thread ", "not currently traced"], 291*2238dcc3SJonas Devlieghere ) 2920b697561SWalter Erquinigo 2930b697561SWalter Erquinigo # We trace again from scratch, this time letting LLDB to pick the current 2940b697561SWalter Erquinigo # thread 2950b697561SWalter Erquinigo self.expect("thread trace start") 2960b697561SWalter Erquinigo self.expect("n") 297*2238dcc3SJonas Devlieghere self.expect( 298*2238dcc3SJonas Devlieghere "thread trace dump instructions -f", 299*2238dcc3SJonas Devlieghere patterns=[ 300*2238dcc3SJonas Devlieghere f"""thread #1: tid = .* 301b0aa7076SWalter Erquinigo a.out`main \+ 20 at main.cpp:5 302*2238dcc3SJonas Devlieghere 2: {ADDRESS_REGEX} xorl""" 303*2238dcc3SJonas Devlieghere ], 304*2238dcc3SJonas Devlieghere ) 305b0aa7076SWalter Erquinigo 306*2238dcc3SJonas Devlieghere self.expect( 307*2238dcc3SJonas Devlieghere "thread trace dump instructions", 308*2238dcc3SJonas Devlieghere patterns=[ 309*2238dcc3SJonas Devlieghere f"""thread #1: tid = .* 3100b697561SWalter Erquinigo a.out`main \+ 20 at main.cpp:5 311*2238dcc3SJonas Devlieghere 2: {ADDRESS_REGEX} xorl""" 312*2238dcc3SJonas Devlieghere ], 313*2238dcc3SJonas Devlieghere ) 314fb19f11eSWalter Erquinigo 315fb19f11eSWalter Erquinigo self.expect("c") 316fb19f11eSWalter Erquinigo # Now the process has finished, so the commands should fail 317*2238dcc3SJonas Devlieghere self.expect( 318*2238dcc3SJonas Devlieghere "thread trace start", 319*2238dcc3SJonas Devlieghere error=True, 320*2238dcc3SJonas Devlieghere substrs=["error: Process must be launched"], 321*2238dcc3SJonas Devlieghere ) 322fb19f11eSWalter Erquinigo 323*2238dcc3SJonas Devlieghere self.expect( 324*2238dcc3SJonas Devlieghere "thread trace stop", error=True, substrs=["error: Process must be launched"] 325*2238dcc3SJonas Devlieghere ) 326a80c6c7dSWalter Erquinigo 327a80c6c7dSWalter Erquinigo # We should be able to trace the program if we relaunch it 328a80c6c7dSWalter Erquinigo # For this, we'll trace starting at a different point in the new 329a80c6c7dSWalter Erquinigo # process. 330a80c6c7dSWalter Erquinigo self.expect("breakpoint disable") 331a80c6c7dSWalter Erquinigo self.expect("b main.cpp:4") 332a80c6c7dSWalter Erquinigo self.expect("r") 333a80c6c7dSWalter Erquinigo self.expect("thread trace start") 334a80c6c7dSWalter Erquinigo # We can reconstruct the single instruction executed in the first line 335a80c6c7dSWalter Erquinigo self.expect("si") 336*2238dcc3SJonas Devlieghere self.expect( 337*2238dcc3SJonas Devlieghere "thread trace dump instructions -c 1", 338*2238dcc3SJonas Devlieghere patterns=[ 339*2238dcc3SJonas Devlieghere f"""thread #1: tid = .* 340*2238dcc3SJonas Devlieghere a.out`main \+ 11 at main.cpp:4""" 341*2238dcc3SJonas Devlieghere ], 342*2238dcc3SJonas Devlieghere ) 343