brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.7 KiB · ebfda62 Raw
399 lines · python
1from intelpt_testcase import *2from lldbsuite.test.lldbtest import *3from lldbsuite.test.decorators import *4 5 6class TestTraceDumpInfo(TraceIntelPTTestCaseBase):7    def testDumpSimpleFunctionCalls(self):8        self.expect(9            "trace load -v "10            + os.path.join(self.getSourceDir(), "intelpt-trace", "trace.json")11        )12 13        self.expect(14            "thread trace dump function-calls 2",15            error=True,16            substrs=['error: no thread with index: "2"'],17        )18 19        self.expect(20            "thread trace dump function-calls 1 -j",21            substrs=[22                '[{"tracedSegments":[{"firstInstructionId":"3","lastInstructionId":"26"}]}]'23            ],24        )25 26        self.expect(27            "thread trace dump function-calls 1 -J",28            substrs=[29                """[30  {31    "tracedSegments": [32      {33        "firstInstructionId": "3",34        "lastInstructionId": "26"35      }36    ]37  }38]"""39            ],40        )41 42        # We test first some code without function call43        self.expect(44            "thread trace dump function-calls 1",45            substrs=[46                """thread #1: tid = 384284947 48[call tree #0]49a.out`main + 4 at main.cpp:2 to 4:0  [3, 26]"""50            ],51        )52 53    def testFunctionCallsWithErrors(self):54        self.expect(55            "trace load -v "56            + os.path.join(57                self.getSourceDir(), "intelpt-multi-core-trace", "trace.json"58            )59        )60 61        # We expect that tracing errors appear as a different tree62        self.expect(63            "thread trace dump function-calls 2",64            substrs=[65                """thread #2: tid = 349749666 67[call tree #0]68m.out`foo() + 65 at multi_thread.cpp:12:21 to 12:21  [4, 19524]69 70[call tree #1]71<tracing errors>  [19526, 19526]"""72            ],73        )74 75        self.expect(76            "thread trace dump function-calls 2 -J",77            substrs=[78                """[79  {80    "tracedSegments": [81      {82        "firstInstructionId": "4",83        "lastInstructionId": "19524"84      }85    ]86  },87  {88    "tracedSegments": [89      {90        "firstInstructionId": "19526",91        "lastInstructionId": "19526"92      }93    ]94  }95]"""96            ],97        )98 99        self.expect(100            "thread trace dump function-calls 3",101            substrs=[102                """thread #3: tid = 3497497103 104[call tree #0]105m.out`bar() + 30 at multi_thread.cpp:19:3 to 20:6  [5, 61831]106 107[call tree #1]108<tracing errors>  [61833, 61833]"""109            ],110        )111 112        self.expect(113            "thread trace dump function-calls 3 -J",114            substrs=[115                """[116  {117    "tracedSegments": [118      {119        "firstInstructionId": "5",120        "lastInstructionId": "61831"121      }122    ]123  },124  {125    "tracedSegments": [126      {127        "firstInstructionId": "61833",128        "lastInstructionId": "61833"129      }130    ]131  }132]"""133            ],134        )135 136    @skipIfNoIntelPT137    def testInlineFunctionCalls(self):138        self.expect(139            "file " + os.path.join(self.getSourceDir(), "inline-function", "a.out")140        )141        self.expect("b main")  # we'll trace from the beginning of main142        self.expect("b 17")143        self.expect("r")144        self.expect("thread trace start")145        self.expect("c")146        self.expect(147            "thread trace dump function-calls",148            substrs=[149                """[call tree #0]150a.out`main + 8 at inline.cpp:15:7 to 16:14  [2, 6]151  a.out`foo(int) at inline.cpp:8:16 to 9:15  [7, 14]152    a.out`foo(int) + 22 [inlined] mult(int, int) at inline.cpp:2:7 to 5:10  [15, 22]153  a.out`foo(int) + 49 at inline.cpp:9:15 to 12:1  [23, 27]154a.out`main + 25 at inline.cpp:16:14 to 16:14  [28, 28]"""155            ],156        )157 158        self.expect(159            "thread trace dump function-calls -J",160            substrs=[161                """[162  {163    "tracedSegments": [164      {165        "firstInstructionId": "2",166        "lastInstructionId": "6",167        "nestedCall": {168          "tracedSegments": [169            {170              "firstInstructionId": "7",171              "lastInstructionId": "14",172              "nestedCall": {173                "tracedSegments": [174                  {175                    "firstInstructionId": "15",176                    "lastInstructionId": "22"177                  }178                ]179              }180            },181            {182              "firstInstructionId": "23",183              "lastInstructionId": "27"184            }185          ]186        }187      },188      {189        "firstInstructionId": "28",190        "lastInstructionId": "28"191      }192    ]193  }194]"""195            ],196        )197 198    @skipIfNoIntelPT199    def testIncompleteInlineFunctionCalls(self):200        self.expect(201            "file " + os.path.join(self.getSourceDir(), "inline-function", "a.out")202        )203        self.expect("b 4")  # we'll trace from the middle of the inline method204        self.expect("b 17")205        self.expect("r")206        self.expect("thread trace start")207        self.expect("c")208        self.expect(209            "thread trace dump function-calls",210            substrs=[211                """[call tree #0]212a.out`main213  a.out`foo(int)214    a.out`foo(int) + 36 [inlined] mult(int, int) + 14 at inline.cpp:4:5 to 5:10  [2, 6]215  a.out`foo(int) + 49 at inline.cpp:9:15 to 12:1  [7, 11]216a.out`main + 25 at inline.cpp:16:14 to 16:14  [12, 12]"""217            ],218        )219 220        self.expect(221            "thread trace dump function-calls -J",222            substrs=[223                """[224  {225    "untracedPrefixSegment": {226      "nestedCall": {227        "untracedPrefixSegment": {228          "nestedCall": {229            "tracedSegments": [230              {231                "firstInstructionId": "2",232                "lastInstructionId": "6"233              }234            ]235          }236        },237        "tracedSegments": [238          {239            "firstInstructionId": "7",240            "lastInstructionId": "11"241          }242        ]243      }244    },245    "tracedSegments": [246      {247        "firstInstructionId": "12",248        "lastInstructionId": "12"249      }250    ]251  }252]"""253            ],254        )255 256    def testMultifileFunctionCalls(self):257        # This test is extremely important because it first calls the method foo() which requires going through the dynamic linking.258        # You'll see the entry "a.out`symbol stub for: foo()" which will invoke the ld linker, which will in turn find the actual foo259        # function and eventually invoke it.  However, we don't have the image of the linker in the trace bundle, so we'll see errors260        # because the decoder couldn't find the linker binary! After those failures, the linker will resume right where we return to261        # main after foo() finished.262        # Then, we call foo() again, but because it has already been loaded by the linker, we don't invoke the linker anymore! And263        # we'll see a nice tree without errors in this second invocation. Something interesting happens here. We still have an264        # invocation to the symbol stub for foo(), but it modifies the stack so that when we return from foo() we don't stop again265        # at the symbol stub, but instead we return directly to main. This is an example of returning several levels up in the266        # call stack.267        # Not only that, we also have an inline method in between.268        self.expect(269            "trace load "270            + os.path.join(271                self.getSourceDir(), "intelpt-trace-multi-file", "multi-file-no-ld.json"272            )273        )274        self.expect(275            "thread trace dump function-calls",276            substrs=[277                """thread #1: tid = 815455278 279[call tree #0]280a.out`main + 15 at main.cpp:10 to 10:0  [3, 3]281  a.out`symbol stub for: foo() to <+11>  [7, 9]282    a.out`a.out[0x0000000000400510] to a.out[0x0000000000400516]  [10, 11]283 284[call tree #1]285<tracing errors>  [12, 12]286 287[call tree #2]288a.out`main + 20 at main.cpp:10 to 12:0  [16, 22]289  a.out`main + 34 [inlined] inline_function() at main.cpp:4 to 6:0  [26, 30]290a.out`main + 55 at main.cpp:14 to 16:0  [31, 37]291  a.out`symbol stub for: foo() to <+0>  [38, 38]292    libfoo.so`foo() at foo.cpp:3 to 4:0  [39, 42]293      libfoo.so`symbol stub for: bar() to <+0>  [43, 43]294        libbar.so`bar() at bar.cpp:1 to 4:0  [44, 52]295    libfoo.so`foo() + 13 at foo.cpp:4 to 6:0  [53, 60]296a.out`main + 68 at main.cpp:16 to 16:0  [61, 63]"""297            ],298        )299 300        self.expect(301            "thread trace dump function-calls -J",302            substrs=[303                """[304  {305    "tracedSegments": [306      {307        "firstInstructionId": "3",308        "lastInstructionId": "3",309        "nestedCall": {310          "tracedSegments": [311            {312              "firstInstructionId": "7",313              "lastInstructionId": "9",314              "nestedCall": {315                "tracedSegments": [316                  {317                    "firstInstructionId": "10",318                    "lastInstructionId": "11"319                  }320                ]321              }322            }323          ]324        }325      }326    ]327  },328  {329    "tracedSegments": [330      {331        "firstInstructionId": "12",332        "lastInstructionId": "12"333      }334    ]335  },336  {337    "tracedSegments": [338      {339        "firstInstructionId": "16",340        "lastInstructionId": "22",341        "nestedCall": {342          "tracedSegments": [343            {344              "firstInstructionId": "26",345              "lastInstructionId": "30"346            }347          ]348        }349      },350      {351        "firstInstructionId": "31",352        "lastInstructionId": "37",353        "nestedCall": {354          "tracedSegments": [355            {356              "firstInstructionId": "38",357              "lastInstructionId": "38",358              "nestedCall": {359                "tracedSegments": [360                  {361                    "firstInstructionId": "39",362                    "lastInstructionId": "42",363                    "nestedCall": {364                      "tracedSegments": [365                        {366                          "firstInstructionId": "43",367                          "lastInstructionId": "43",368                          "nestedCall": {369                            "tracedSegments": [370                              {371                                "firstInstructionId": "44",372                                "lastInstructionId": "52"373                              }374                            ]375                          }376                        }377                      ]378                    }379                  },380                  {381                    "firstInstructionId": "53",382                    "lastInstructionId": "60"383                  }384                ]385              }386            }387          ]388        }389      },390      {391        "firstInstructionId": "61",392        "lastInstructionId": "63"393      }394    ]395  }396]"""397            ],398        )399