344 lines · python
1import lldb2from intelpt_testcase import *3from lldbsuite.test.lldbtest import *4from lldbsuite.test import lldbutil5from lldbsuite.test.decorators import *6 7 8@skipIfNoIntelPT9class TestTraceStartStop(TraceIntelPTTestCaseBase):10 def expectGenericHelpMessageForStartCommand(self):11 self.expect(12 "help thread trace start",13 substrs=["Syntax: thread trace start [<trace-options>]"],14 )15 16 @testSBAPIAndCommands17 def testStartStopSessionFileThreads(self):18 # it should fail for processes from json session files19 self.expect(20 "trace load -v "21 + os.path.join(self.getSourceDir(), "intelpt-trace", "trace.json")22 )23 24 # the help command should be the generic one, as it's not a live process25 self.expectGenericHelpMessageForStartCommand()26 27 self.traceStartThread(error=True)28 29 self.traceStopThread(error=True)30 31 @testSBAPIAndCommands32 def testStartWithNoProcess(self):33 self.traceStartThread(error=True)34 35 @testSBAPIAndCommands36 def testStartSessionWithWrongSize(self):37 self.expect(38 "file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out")39 )40 self.expect("b main")41 self.expect("r")42 43 self.traceStartThread(44 error=True,45 iptTraceSize=2000,46 substrs=["The intel pt trace size must be a power of 2", "It was 2000"],47 )48 49 self.traceStartThread(50 error=True,51 iptTraceSize=5000,52 substrs=["The intel pt trace size must be a power of 2", "It was 5000"],53 )54 55 self.traceStartThread(56 error=True,57 iptTraceSize=0,58 substrs=["The intel pt trace size must be a power of 2", "It was 0"],59 )60 61 self.traceStartThread(iptTraceSize=1048576)62 63 @testSBAPIAndCommands64 def testStartSessionWithSizeDeclarationInUnits(self):65 self.expect(66 "file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out")67 )68 self.expect("b main")69 self.expect("r")70 71 self.traceStartThread(72 error=True,73 iptTraceSize="abc",74 substrs=["invalid bytes expression for 'abc'"],75 )76 77 self.traceStartThread(78 error=True,79 iptTraceSize="123.12",80 substrs=["invalid bytes expression for '123.12'"],81 )82 83 self.traceStartThread(84 error=True, iptTraceSize='""', substrs=["invalid bytes expression for ''"]85 )86 87 self.traceStartThread(88 error=True,89 iptTraceSize="2000B",90 substrs=[91 "The intel pt trace size must be a power of 2 greater than or equal to 4096 (2^12) bytes. It was 2000"92 ],93 )94 95 self.traceStartThread(96 error=True,97 iptTraceSize="3MB",98 substrs=[99 "The intel pt trace size must be a power of 2 greater than or equal to 4096 (2^12) bytes. It was 3145728"100 ],101 )102 103 self.traceStartThread(104 error=True,105 iptTraceSize="3MiB",106 substrs=[107 "The intel pt trace size must be a power of 2 greater than or equal to 4096 (2^12) bytes. It was 3145728"108 ],109 )110 111 self.traceStartThread(112 error=True,113 iptTraceSize="3mib",114 substrs=[115 "The intel pt trace size must be a power of 2 greater than or equal to 4096 (2^12) bytes. It was 3145728"116 ],117 )118 119 self.traceStartThread(120 error=True,121 iptTraceSize="3M",122 substrs=[123 "The intel pt trace size must be a power of 2 greater than or equal to 4096 (2^12) bytes. It was 3145728"124 ],125 )126 127 self.traceStartThread(128 error=True,129 iptTraceSize="3KB",130 substrs=[131 "The intel pt trace size must be a power of 2 greater than or equal to 4096 (2^12) bytes. It was 3072"132 ],133 )134 135 self.traceStartThread(136 error=True,137 iptTraceSize="3KiB",138 substrs=[139 "The intel pt trace size must be a power of 2 greater than or equal to 4096 (2^12) bytes. It was 3072"140 ],141 )142 143 self.traceStartThread(144 error=True,145 iptTraceSize="3K",146 substrs=[147 "The intel pt trace size must be a power of 2 greater than or equal to 4096 (2^12) bytes. It was 3072"148 ],149 )150 151 self.traceStartThread(152 error=True,153 iptTraceSize="3MS",154 substrs=["invalid bytes expression for '3MS'"],155 )156 157 self.traceStartThread(iptTraceSize="1048576")158 159 @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"]))160 def testSBAPIHelp(self):161 self.expect(162 "file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out")163 )164 self.expect("b main")165 self.expect("r")166 167 help = self.getTraceOrCreate().GetStartConfigurationHelp()168 self.assertIn("iptTraceSize", help)169 self.assertIn("processBufferSizeLimit", help)170 171 @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"]))172 def testStoppingAThread(self):173 self.expect(174 "file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out")175 )176 self.expect("b main")177 self.expect("r")178 self.expect("thread trace start")179 self.expect("n")180 self.expect(181 "thread trace dump instructions",182 substrs=[183 """0x0000000000400511 movl $0x0, -0x4(%rbp)184 no more data"""185 ],186 )187 # process stopping should stop the thread188 self.expect("process trace stop")189 self.expect("n")190 self.expect(191 "thread trace dump instructions", substrs=["not traced"], error=True192 )193 194 @skipIf(oslist=no_match(["linux"]), archs=no_match(["i386", "x86_64"]))195 def testStartStopLiveThreads(self):196 # The help command should be the generic one if there's no process running197 self.expectGenericHelpMessageForStartCommand()198 199 self.expect(200 "thread trace start", error=True, substrs=["error: Process not available"]201 )202 203 self.expect(204 "file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out")205 )206 self.expect("b main")207 208 self.expect(209 "thread trace start", error=True, substrs=["error: Process not available"]210 )211 212 # The help command should be the generic one if there's still no process running213 self.expectGenericHelpMessageForStartCommand()214 215 self.expect("r")216 217 # This fails because "trace start" hasn't been called yet218 self.expect(219 "thread trace stop",220 error=True,221 substrs=["error: Process is not being traced"],222 )223 224 # the help command should be the intel-pt one now225 self.expect(226 "help thread trace start",227 substrs=[228 "Start tracing one or more threads with intel-pt.",229 "Syntax: thread trace start [<thread-index> <thread-index> ...] [<intel-pt-options>]",230 ],231 )232 233 # We start tracing with a small buffer size234 self.expect("thread trace start 1 --size 4096")235 236 # We fail if we try to trace again237 self.expect(238 "thread trace start",239 error=True,240 substrs=["error: Thread ", "already traced"],241 )242 243 # We can reconstruct the single instruction executed in the first line244 self.expect("n")245 self.expect(246 "thread trace dump instructions -f",247 patterns=[248 rf"""thread #1: tid = .*249 a.out`main \+ 4 at main.cpp:2250 2: {ADDRESS_REGEX} movl"""251 ],252 )253 254 # We can reconstruct the instructions up to the second line255 self.expect("n")256 self.expect(257 "thread trace dump instructions -f",258 patterns=[259 rf"""thread #1: tid = .*260 a.out`main \+ 4 at main.cpp:2261 2: {ADDRESS_REGEX} movl .*262 a.out`main \+ 11 at main.cpp:4263 4: {ADDRESS_REGEX} movl .*264 6: {ADDRESS_REGEX} jmp .* ; <\+28> at main.cpp:4265 8: {ADDRESS_REGEX} cmpl .*266 10: {ADDRESS_REGEX} jle .* ; <\+20> at main.cpp:5"""267 ],268 )269 270 self.expect(271 "thread trace dump instructions",272 patterns=[273 rf"""thread #1: tid = .*274 a.out`main \+ 32 at main.cpp:4275 10: {ADDRESS_REGEX} jle .* ; <\+20> at main.cpp:5276 8: {ADDRESS_REGEX} cmpl .*277 6: {ADDRESS_REGEX} jmp .* ; <\+28> at main.cpp:4278 4: {ADDRESS_REGEX} movl .*279 a.out`main \+ 4 at main.cpp:2280 2: {ADDRESS_REGEX} movl .* """281 ],282 )283 284 # We stop tracing285 self.expect("thread trace stop")286 287 # We can't stop twice288 self.expect(289 "thread trace stop",290 error=True,291 substrs=["error: Thread ", "not currently traced"],292 )293 294 # We trace again from scratch, this time letting LLDB to pick the current295 # thread296 self.expect("thread trace start")297 self.expect("n")298 self.expect(299 "thread trace dump instructions -f",300 patterns=[301 rf"""thread #1: tid = .*302 a.out`main \+ 20 at main.cpp:5303 2: {ADDRESS_REGEX} xorl"""304 ],305 )306 307 self.expect(308 "thread trace dump instructions",309 patterns=[310 rf"""thread #1: tid = .*311 a.out`main \+ 20 at main.cpp:5312 2: {ADDRESS_REGEX} xorl"""313 ],314 )315 316 self.expect("c")317 # Now the process has finished, so the commands should fail318 self.expect(319 "thread trace start",320 error=True,321 substrs=["error: Process must be launched"],322 )323 324 self.expect(325 "thread trace stop", error=True, substrs=["error: Process must be launched"]326 )327 328 # We should be able to trace the program if we relaunch it329 # For this, we'll trace starting at a different point in the new330 # process.331 self.expect("breakpoint disable")332 self.expect("b main.cpp:4")333 self.expect("r")334 self.expect("thread trace start")335 # We can reconstruct the single instruction executed in the first line336 self.expect("si")337 self.expect(338 "thread trace dump instructions -c 1",339 patterns=[340 rf"""thread #1: tid = .*341 a.out`main \+ 11 at main.cpp:4"""342 ],343 )344