brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.7 KiB · db52493 Raw
556 lines · python
1import lldb2from intelpt_testcase import *3from lldbsuite.test.lldbtest import *4from lldbsuite.test import lldbutil5from lldbsuite.test.decorators import *6 7 8class TestTraceLoad(TraceIntelPTTestCaseBase):9    NO_DEBUG_INFO_TESTCASE = True10 11    @testSBAPIAndCommands12    def testLoadMultiCoreTrace(self):13        src_dir = self.getSourceDir()14        trace_description_file_path = os.path.join(15            src_dir, "intelpt-multi-core-trace", "trace.json"16        )17        self.traceLoad(18            traceDescriptionFilePath=trace_description_file_path, substrs=["intel-pt"]19        )20        self.expect(21            "thread trace dump instructions 2 -t",22            substrs=[23                "19526: [19691636.212 ns] (error) decoding truncated: TSC 40450075478109270 exceeds maximum TSC value 40450075477704372, will skip decoding the remaining data of the PSB (skipping 774 of 825 bytes)",24                "m.out`foo() + 65 at multi_thread.cpp:12:21",25                "9524: [19691632.221 ns] 0x0000000000400ba7    jg     0x400bb3",26            ],27        )28        self.expect(29            "thread trace dump instructions 3 -t",30            substrs=[31                "61831: [19736132.088 ns] 0x0000000000400bd7    addl   $0x1, -0x4(%rbp)",32                "m.out`bar() + 26 at multi_thread.cpp:20:6",33            ],34        )35 36        self.expect(37            "thread trace dump info --json",38            substrs=[39                """{40  "traceTechnology": "intel-pt",41  "threadStats": {42    "tid": 3497234,43    "traceItemsCount": 0,44    "memoryUsage": {45      "totalInBytes": "0",46      "avgPerItemInBytes": null47    },48    "timingInSeconds": {49      "Decoding instructions": """,50                """51    },52    "events": {53      "totalCount": 0,54      "individualCounts": {}55    },56    "errors": {57      "totalCount": 0,58      "libiptErrors": {},59      "fatalErrors": 0,60      "otherErrors": 061    },62    "continuousExecutions": 0,63    "PSBBlocks": 064  },65  "globalStats": {66    "timingInSeconds": {67      "Context switch and Intel PT traces correlation": 068    },69    "totalUnattributedPSBBlocks": 0,70    "totalCountinuosExecutions": 153,71    "totalPSBBlocks": 5,72    "totalContinuousExecutions": 15373  }74}""",75            ],76        )77 78        self.expect(79            "thread trace dump info 2 --json",80            substrs=[81                """{82  "traceTechnology": "intel-pt",83  "threadStats": {84    "tid": 3497496,85    "traceItemsCount": 19527,""",86                """},87    "timingInSeconds": {88      "Decoding instructions": """,89                """90    },91    "events": {92      "totalCount": 5,93      "individualCounts": {94        "software disabled tracing": 1,95        "trace synchronization point": 1,96        "CPU core changed": 1,97        "HW clock tick": 298      }99    },100    "errors": {101      "totalCount": 1,102      "libiptErrors": {},103      "fatalErrors": 0,104      "otherErrors": 1105    },106    "continuousExecutions": 1,107    "PSBBlocks": 1108  },109  "globalStats": {110    "timingInSeconds": {111      "Context switch and Intel PT traces correlation": 0""",112                """},113    "totalUnattributedPSBBlocks": 0,114    "totalCountinuosExecutions": 153,115    "totalPSBBlocks": 5,116    "totalContinuousExecutions": 153117  }118}""",119            ],120        )121 122    @testSBAPIAndCommands123    def testLoadCompactMultiCoreTrace(self):124        src_dir = self.getSourceDir()125        trace_description_file_path = os.path.join(126            src_dir, "intelpt-multi-core-trace", "trace.json"127        )128        self.traceLoad(129            traceDescriptionFilePath=trace_description_file_path, substrs=["intel-pt"]130        )131 132        self.expect(133            "thread trace dump info 2",134            substrs=["Total number of continuous executions found: 153"],135        )136 137        # we'll save the trace in compact format138        compact_trace_bundle_dir = os.path.join(139            self.getBuildDir(), "intelpt-multi-core-trace-compact"140        )141        self.traceSave(compact_trace_bundle_dir, compact=True)142 143        # we'll delete the previous target and make sure it's trace object is deleted144        self.dbg.DeleteTarget(self.dbg.GetTargetAtIndex(0))145        self.expect(146            "thread trace dump instructions 2 -t",147            substrs=["error: invalid target"],148            error=True,149        )150 151        # we'll load the compact trace and make sure it works152        self.traceLoad(153            os.path.join(compact_trace_bundle_dir, "trace.json"), substrs=["intel-pt"]154        )155        self.expect(156            "thread trace dump instructions 2 -t",157            substrs=[158                "19526: [19691636.212 ns] (error)",159                "m.out`foo() + 65 at multi_thread.cpp:12:21",160                "19524: [19691632.221 ns] 0x0000000000400ba7    jg     0x400bb3",161            ],162        )163        self.expect(164            "thread trace dump instructions 3 -t",165            substrs=[166                "61833: [19736136.079 ns] (error)",167                "61831: [19736132.088 ns] 0x0000000000400bd7    addl   $0x1, -0x4(%rbp)",168                "m.out`bar() + 26 at multi_thread.cpp:20:6",169            ],170        )171 172        # This reduced the number of continuous executions to look at173        self.expect(174            "thread trace dump info 2",175            substrs=["Total number of continuous executions found: 3"],176        )177 178        # We clean up for the next run of this test179        self.dbg.DeleteTarget(self.dbg.GetTargetAtIndex(0))180 181    @testSBAPIAndCommands182    def testLoadMultiCoreTraceWithStringNumbers(self):183        src_dir = self.getSourceDir()184        trace_description_file_path = os.path.join(185            src_dir, "intelpt-multi-core-trace", "trace_with_string_numbers.json"186        )187        self.traceLoad(188            traceDescriptionFilePath=trace_description_file_path, substrs=["intel-pt"]189        )190        self.expect(191            "thread trace dump instructions 2 -t",192            substrs=[193                "19526: [19691636.212 ns] (error)",194                "m.out`foo() + 65 at multi_thread.cpp:12:21",195                "19524: [19691632.221 ns] 0x0000000000400ba7    jg     0x400bb3",196            ],197        )198        self.expect(199            "thread trace dump instructions 3 -t",200            substrs=[201                "61831: [19736132.088 ns] 0x0000000000400bd7    addl   $0x1, -0x4(%rbp)",202                "m.out`bar() + 26 at multi_thread.cpp:20:6",203            ],204        )205 206    @testSBAPIAndCommands207    def testLoadMultiCoreTraceWithMissingThreads(self):208        src_dir = self.getSourceDir()209        trace_description_file_path = os.path.join(210            src_dir, "intelpt-multi-core-trace", "trace_missing_threads.json"211        )212        self.traceLoad(213            traceDescriptionFilePath=trace_description_file_path, substrs=["intel-pt"]214        )215        self.expect(216            "thread trace dump instructions 3 -t",217            substrs=[218                "19526: [19691636.212 ns] (error)",219                "m.out`foo() + 65 at multi_thread.cpp:12:21",220                "19524: [19691632.221 ns] 0x0000000000400ba7    jg     0x400bb3",221            ],222        )223        self.expect(224            "thread trace dump instructions 2 -t",225            substrs=[226                "61831: [19736132.088 ns] 0x0000000000400bd7    addl   $0x1, -0x4(%rbp)",227                "m.out`bar() + 26 at multi_thread.cpp:20:6",228            ],229        )230 231    @testSBAPIAndCommands232    def testLoadTrace(self):233        src_dir = self.getSourceDir()234        trace_description_file_path = os.path.join(235            src_dir, "intelpt-trace", "trace.json"236        )237        self.traceLoad(238            traceDescriptionFilePath=trace_description_file_path, substrs=["intel-pt"]239        )240 241        target = self.dbg.GetSelectedTarget()242        process = target.GetProcess()243        self.assertEqual(process.GetProcessID(), 1234)244 245        self.assertEqual(process.GetNumThreads(), 1)246        self.assertEqual(process.GetThreadAtIndex(0).GetThreadID(), 3842849)247 248        self.assertEqual(target.GetNumModules(), 1)249        module = target.GetModuleAtIndex(0)250        path = module.GetFileSpec()251        self.assertEqual(path.fullpath, os.path.join(src_dir, "intelpt-trace", "a.out"))252        self.assertGreater(module.GetNumSections(), 0)253        self.assertEqual(module.GetSectionAtIndex(0).GetFileAddress(), 0x400000)254 255        self.assertEqual(256            "6AA9A4E2-6F28-2F33-377D-59FECE874C71-5B41261A", module.GetUUIDString()257        )258 259        # check that the Process and Thread objects were created correctly260        self.expect("thread info", substrs=["tid = 3842849"])261        self.expect("thread list", substrs=["Process 1234 stopped", "tid = 3842849"])262        self.expect(263            "thread trace dump info",264            substrs=[265                """thread #1: tid = 3842849266 267  Trace technology: intel-pt268 269  Total number of trace items: 28270 271  Memory usage:272    Raw trace size: 4 KiB""",273                """274 275  Events:276    Number of individual events: 7277      software disabled tracing: 2278      hardware disabled tracing: 4279      trace synchronization point: 1""",280            ],281        )282 283    @testSBAPIAndCommands284    def testLoadInvalidTraces(self):285        src_dir = self.getSourceDir()286 287        # We test first an invalid type288        trace_description_file_path = os.path.join(289            src_dir, "intelpt-trace", "trace_bad.json"290        )291        expected_substrs = [292            """error: expected object at traceBundle.processes[0]293 294Context:295{296  "cpuInfo": { ... },297  "processes": [298    /* error: expected object */299    123300  ],301  "type": "intel-pt"302}303 304Schema:305{306  "type": "intel-pt",307  "cpuInfo": {308    // CPU information gotten from, for example, /proc/cpuinfo.309 310    "vendor": "GenuineIntel" | "unknown",311    "family": integer,312    "model": integer,313    "stepping": integer314  },"""315        ]316        self.traceLoad(317            traceDescriptionFilePath=trace_description_file_path,318            error=True,319            substrs=expected_substrs,320        )321 322        # Now we test a wrong cpu family field in the global bundle description file323        trace_description_file_path = os.path.join(324            src_dir, "intelpt-trace", "trace_bad2.json"325        )326        expected_substrs = [327            "error: expected uint64_t at traceBundle.cpuInfo.family",328            "Context",329            "Schema",330        ]331        self.traceLoad(332            traceDescriptionFilePath=trace_description_file_path,333            error=True,334            substrs=expected_substrs,335        )336 337        # Now we test a missing field in the intel-pt settings338        trace_description_file_path = os.path.join(339            src_dir, "intelpt-trace", "trace_bad4.json"340        )341        expected_substrs = [342            """error: missing value at traceBundle.cpuInfo.family343 344Context:345{346  "cpuInfo": /* error: missing value */ {347    "model": 79,348    "stepping": 1,349    "vendor": "GenuineIntel"350  },351  "processes": [],352  "type": "intel-pt"353}""",354            "Schema",355        ]356        self.traceLoad(357            traceDescriptionFilePath=trace_description_file_path,358            error=True,359            substrs=expected_substrs,360        )361 362        # Now we test an incorrect load address in the intel-pt settings363        trace_description_file_path = os.path.join(364            src_dir, "intelpt-trace", "trace_bad5.json"365        )366        expected_substrs = [367            "error: missing value at traceBundle.processes[1].pid",368            "Schema",369        ]370        self.traceLoad(371            traceDescriptionFilePath=trace_description_file_path,372            error=True,373            substrs=expected_substrs,374        )375 376        # The following wrong schema will have a valid target and an invalid one. In the case of failure,377        # no targets should be created.378        self.assertEqual(self.dbg.GetNumTargets(), 0)379        trace_description_file_path = os.path.join(380            src_dir, "intelpt-trace", "trace_bad3.json"381        )382        expected_substrs = ["error: missing value at traceBundle.processes[1].pid"]383        self.traceLoad(384            traceDescriptionFilePath=trace_description_file_path,385            error=True,386            substrs=expected_substrs,387        )388        self.assertEqual(self.dbg.GetNumTargets(), 0)389 390    def testLoadTraceCursor(self):391        src_dir = self.getSourceDir()392        trace_description_file_path = os.path.join(393            src_dir, "intelpt-multi-core-trace", "trace.json"394        )395        traceDescriptionFile = lldb.SBFileSpec(trace_description_file_path, True)396 397        error = lldb.SBError()398        trace = self.dbg.LoadTraceFromFile(error, traceDescriptionFile)399        self.assertSBError(error)400 401        target = self.dbg.GetSelectedTarget()402        process = target.process403 404        # 1. Test some expected items of thread 1's trace cursor.405        thread1 = process.threads[1]406        cursor = trace.CreateNewCursor(error, thread1)407        self.assertTrue(cursor)408        self.assertTrue(cursor.HasValue())409        cursor.Seek(0, lldb.eTraceCursorSeekTypeBeginning)410        cursor.SetForwards(True)411 412        self.assertTrue(cursor.IsEvent())413        self.assertEqual(cursor.GetEventTypeAsString(), "HW clock tick")414        self.assertEqual(cursor.GetCPU(), lldb.LLDB_INVALID_CPU_ID)415 416        cursor.Next()417 418        self.assertTrue(cursor.IsEvent())419        self.assertEqual(cursor.GetEventTypeAsString(), "CPU core changed")420        self.assertEqual(cursor.GetCPU(), 51)421 422        cursor.GoToId(19526)423 424        self.assertTrue(cursor.IsError())425        self.assertEqual(426            cursor.GetError(),427            "decoding truncated: TSC 40450075478109270 exceeds maximum TSC value 40450075477704372, will skip decoding the remaining data of the PSB (skipping 774 of 825 bytes)",428        )429 430        cursor.GoToId(19524)431 432        self.assertTrue(cursor.IsInstruction())433        self.assertEqual(cursor.GetLoadAddress(), 0x400BA7)434 435        # Helper function to check equality of the current item of two trace cursors.436        def assertCurrentTraceCursorItemEqual(lhs, rhs):437            self.assertTrue(lhs.HasValue() and rhs.HasValue())438 439            self.assertEqual(lhs.GetId(), rhs.GetId())440            self.assertEqual(lhs.GetItemKind(), rhs.GetItemKind())441            if lhs.IsError():442                self.assertEqual(lhs.GetError(), rhs.GetError())443            elif lhs.IsEvent():444                self.assertEqual(lhs.GetEventType(), rhs.GetEventType())445                self.assertEqual(lhs.GetEventTypeAsString(), rhs.GetEventTypeAsString())446            elif lhs.IsInstruction():447                self.assertEqual(lhs.GetLoadAddress(), rhs.GetLoadAddress())448            else:449                self.fail("Unknown trace item kind")450 451        for thread in process.threads:452            sequentialTraversalCursor = trace.CreateNewCursor(error, thread)453            self.assertSBError(error)454            # Skip threads with no trace items455            if not sequentialTraversalCursor.HasValue():456                continue457 458            # 2. Test "End" boundary of the trace by advancing past the trace's last item.459            sequentialTraversalCursor.Seek(0, lldb.eTraceCursorSeekTypeEnd)460            self.assertTrue(sequentialTraversalCursor.HasValue())461            sequentialTraversalCursor.SetForwards(True)462            sequentialTraversalCursor.Next()463            self.assertFalse(sequentialTraversalCursor.HasValue())464 465            # 3. Test sequential traversal using sequential access API (ie Next())466            # and random access API (ie GoToId()) simultaneously.467            randomAccessCursor = trace.CreateNewCursor(error, thread)468            self.assertSBError(error)469            # Reset the sequential cursor470            sequentialTraversalCursor.Seek(0, lldb.eTraceCursorSeekTypeBeginning)471            sequentialTraversalCursor.SetForwards(True)472            self.assertTrue(sequentialTraversalCursor.IsForwards())473 474            while sequentialTraversalCursor.HasValue():475                itemId = sequentialTraversalCursor.GetId()476                randomAccessCursor.GoToId(itemId)477                assertCurrentTraceCursorItemEqual(478                    sequentialTraversalCursor, randomAccessCursor479                )480                sequentialTraversalCursor.Next()481 482            # 4. Test a random access with random access API (ie Seek()) and483            # sequential access API (ie consecutive calls to Next()).484            TEST_SEEK_ID = 3485            randomAccessCursor.GoToId(TEST_SEEK_ID)486            # Reset the sequential cursor487            sequentialTraversalCursor.Seek(0, lldb.eTraceCursorSeekTypeBeginning)488            sequentialTraversalCursor.SetForwards(True)489            for _ in range(TEST_SEEK_ID):490                sequentialTraversalCursor.Next()491            assertCurrentTraceCursorItemEqual(492                sequentialTraversalCursor, randomAccessCursor493            )494 495    @testSBAPIAndCommands496    def testLoadKernelTrace(self):497        # kernel section without loadAddress (using default loadAddress).498        src_dir = self.getSourceDir()499        trace_description_file_path = os.path.join(500            src_dir, "intelpt-kernel-trace", "trace.json"501        )502        self.traceLoad(503            traceDescriptionFilePath=trace_description_file_path, substrs=["intel-pt"]504        )505 506        self.expect("image list", substrs=["0xffffffff81000000", "modules/m.out"])507 508        self.expect(509            "thread list",510            substrs=[511                "Process 1 stopped",512                "* thread #1: tid = 0x002d",513                "  thread #2: tid = 0x0033",514            ],515        )516 517        # kernel section with custom loadAddress.518        trace_description_file_path = os.path.join(519            src_dir, "intelpt-kernel-trace", "trace_with_loadAddress.json"520        )521        self.traceLoad(522            traceDescriptionFilePath=trace_description_file_path, substrs=["intel-pt"]523        )524 525        self.expect("image list", substrs=["0x400000", "modules/m.out"])526 527    @testSBAPIAndCommands528    def testLoadInvalidKernelTrace(self):529        src_dir = self.getSourceDir()530 531        # Test kernel section with non-empty processeses section.532        trace_description_file_path = os.path.join(533            src_dir, "intelpt-kernel-trace", "trace_kernel_with_process.json"534        )535        expected_substrs = [536            'error: "processes" must be empty when "kernel" is provided when parsing traceBundle'537        ]538        self.traceLoad(539            traceDescriptionFilePath=trace_description_file_path,540            error=True,541            substrs=expected_substrs,542        )543 544        # Test kernel section without cpus section.545        trace_description_file_path = os.path.join(546            src_dir, "intelpt-kernel-trace", "trace_kernel_wo_cpus.json"547        )548        expected_substrs = [549            'error: "cpus" is required when "kernel" is provided when parsing traceBundle'550        ]551        self.traceLoad(552            traceDescriptionFilePath=trace_description_file_path,553            error=True,554            substrs=expected_substrs,555        )556