brintos

brintos / llvm-project-archived public Read only

0
0
Text · 21.0 KiB · fa4d38f Raw
640 lines · python
1from intelpt_testcase import *2from lldbsuite.test.lldbtest import *3from lldbsuite.test.decorators import *4 5 6class TestTraceDumpInstructions(TraceIntelPTTestCaseBase):7    def testErrorMessages(self):8        # We first check the output when there are no targets9        self.expect(10            "thread trace dump instructions",11            substrs=[12                "error: invalid target, create a target using the 'target create' command"13            ],14            error=True,15        )16 17        # We now check the output when there's a non-running target18        self.expect(19            "target create "20            + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out")21        )22 23        self.expect(24            "thread trace dump instructions",25            substrs=["error: Command requires a current process."],26            error=True,27        )28 29        # Now we check the output when there's a running target without a trace30        self.expect("b main")31        self.expect("run")32 33        self.expect(34            "thread trace dump instructions",35            substrs=["error: Process is not being traced"],36            error=True,37        )38 39    def testRawDumpInstructionsInJSON(self):40        self.expect(41            "trace load -v "42            + os.path.join(self.getSourceDir(), "intelpt-trace", "trace.json"),43            substrs=["intel-pt"],44        )45 46        self.expect(47            "thread trace dump instructions --raw --count 5 --forwards --json",48            substrs=[49                """[{"id":3,"loadAddress":"0x400511"}""",50                """{"id":7,"loadAddress":"0x400518"}""",51                """{"id":8,"loadAddress":"0x40051f"}""",52                """{"id":9,"loadAddress":"0x400529"}""",53                """{"id":10,"loadAddress":"0x40052d"}""",54            ],55        )56 57        self.expect(58            "thread trace dump instructions --raw --count 5 --forwards --pretty-json",59            substrs=[60                """[61  {62    "id": 3,63    "loadAddress": "0x400511"64  },65  {66    "id": 7,67    "loadAddress": "0x400518"68  },69  {70    "id": 8,71    "loadAddress": "0x40051f"72  },73  {74    "id": 9,75    "loadAddress": "0x400529"76  },77  {78    "id": 10,79    "loadAddress": "0x40052d"80  }81]"""82            ],83        )84 85    def testRawDumpInstructionsInJSONToFile(self):86        self.expect(87            "trace load -v "88            + os.path.join(self.getSourceDir(), "intelpt-trace", "trace.json"),89            substrs=["intel-pt"],90        )91 92        outfile = os.path.join(self.getBuildDir(), "output.json")93 94        self.expect(95            "thread trace dump instructions --raw --count 5 --forwards --pretty-json --file "96            + outfile97        )98 99        with open(outfile, "r") as out:100            self.assertEqual(101                out.read(),102                """[103  {104    "id": 3,105    "loadAddress": "0x400511"106  },107  {108    "id": 7,109    "loadAddress": "0x400518"110  },111  {112    "id": 8,113    "loadAddress": "0x40051f"114  },115  {116    "id": 9,117    "loadAddress": "0x400529"118  },119  {120    "id": 10,121    "loadAddress": "0x40052d"122  }123]""",124            )125 126    def testRawDumpInstructions(self):127        self.expect(128            "trace load -v "129            + os.path.join(self.getSourceDir(), "intelpt-trace", "trace.json"),130            substrs=["intel-pt"],131        )132 133        self.expect(134            "thread trace dump instructions --raw --count 21 --forwards",135            substrs=[136                """thread #1: tid = 3842849137    3: 0x0000000000400511138    7: 0x0000000000400518139    8: 0x000000000040051f140    9: 0x0000000000400529141    10: 0x000000000040052d142    11: 0x0000000000400521143    12: 0x0000000000400525144    13: 0x0000000000400529145    14: 0x000000000040052d146    15: 0x0000000000400521147    16: 0x0000000000400525148    17: 0x0000000000400529149    18: 0x000000000040052d150    19: 0x0000000000400521151    20: 0x0000000000400525152    21: 0x0000000000400529153    22: 0x000000000040052d154    23: 0x0000000000400521155    24: 0x0000000000400525156    25: 0x0000000000400529157    26: 0x000000000040052"""158            ],159        )160 161        # We check if we can pass count and skip162        self.expect(163            "thread trace dump instructions --count 5 --skip 6 --raw --forwards",164            substrs=[165                """thread #1: tid = 3842849166    7: 0x0000000000400518167    8: 0x000000000040051f168    9: 0x0000000000400529169    10: 0x000000000040052d170    11: 0x0000000000400521"""171            ],172        )173 174        self.expect(175            "thread trace dump instructions --count 5 --skip 6 --raw",176            substrs=[177                """thread #1: tid = 3842849178    21: 0x0000000000400529179    20: 0x0000000000400525180    19: 0x0000000000400521181    18: 0x000000000040052d182    17: 0x0000000000400529"""183            ],184        )185 186        # We check if we can pass count and skip and instruction id in hex187        self.expect(188            "thread trace dump instructions --count 5 --skip 6 --raw --id 0xE",189            substrs=[190                """thread #1: tid = 3842849191    8: 0x000000000040051f192    7: 0x0000000000400518193    3: 0x0000000000400511194    no more data"""195            ],196        )197 198        # We check if we can pass count and skip and instruction id in decimal199        self.expect(200            "thread trace dump instructions --count 5 --skip 6 --raw --id 14",201            substrs=[202                """thread #1: tid = 3842849203    8: 0x000000000040051f204    7: 0x0000000000400518205    3: 0x0000000000400511206    no more data"""207            ],208        )209 210        # We check if we can access the thread by index id211        self.expect(212            "thread trace dump instructions 1 --raw",213            substrs=[214                """thread #1: tid = 3842849215    26: 0x000000000040052d"""216            ],217        )218 219        # We check that we get an error when using an invalid thread index id220        self.expect(221            "thread trace dump instructions 10",222            error=True,223            substrs=['error: no thread with index: "10"'],224        )225 226    def testDumpFullInstructionsWithMultipleThreads(self):227        # We load a trace with two threads228        self.expect(229            "trace load -v "230            + os.path.join(self.getSourceDir(), "intelpt-trace", "trace_2threads.json")231        )232 233        # We print the instructions of a specific thread234        self.expect(235            "thread trace dump instructions 2 --count 2",236            substrs=[237                """thread #2: tid = 3842850238  a.out`main + 32 at main.cpp:4239    26: 0x000000000040052d    jle    0x400521                  ; <+20> at main.cpp:5240    25: 0x0000000000400529    cmpl   $0x3, -0x8(%rbp)"""241            ],242        )243 244        # We use custom --count and --skip, saving the command to history for later245        self.expect(246            "thread trace dump instructions 2 --count 2 --skip 2",247            inHistory=True,248            substrs=[249                """thread #2: tid = 3842850250  a.out`main + 28 at main.cpp:4251    25: 0x0000000000400529    cmpl   $0x3, -0x8(%rbp)252    24: 0x0000000000400525    addl   $0x1, -0x8(%rbp)"""253            ],254        )255 256        # We use a repeat command twice and ensure the previous count is used and the257        # start position moves with each command.258        self.expect(259            "",260            inHistory=True,261            substrs=[262                """thread #2: tid = 3842850263  a.out`main + 20 at main.cpp:5264    23: 0x0000000000400521    xorl   $0x1, -0x4(%rbp)265  a.out`main + 32 at main.cpp:4266    22: 0x000000000040052d    jle    0x400521                  ; <+20> at main.cpp:5"""267            ],268        )269 270        self.expect(271            "",272            inHistory=True,273            substrs=[274                """thread #2: tid = 3842850275  a.out`main + 28 at main.cpp:4276    21: 0x0000000000400529    cmpl   $0x3, -0x8(%rbp)277    20: 0x0000000000400525    addl   $0x1, -0x8(%rbp"""278            ],279        )280 281    def testInvalidBounds(self):282        self.expect(283            "trace load -v "284            + os.path.join(self.getSourceDir(), "intelpt-trace", "trace.json")285        )286 287        # The output should be work when too many instructions are asked288        self.expect(289            "thread trace dump instructions --count 20 --forwards",290            substrs=[291                """thread #1: tid = 3842849292  a.out`main + 4 at main.cpp:2293    3: 0x0000000000400511    movl   $0x0, -0x4(%rbp)294  a.out`main + 11 at main.cpp:4295    7: 0x0000000000400518    movl   $0x0, -0x8(%rbp)296    8: 0x000000000040051f    jmp    0x400529                  ; <+28> at main.cpp:4"""297            ],298        )299 300        # Should print no instructions if the position is out of bounds301        self.expect("thread trace dump instructions --skip 23", endstr="no more data\n")302 303        # Should fail with negative bounds304        self.expect("thread trace dump instructions --skip -1", error=True)305        self.expect("thread trace dump instructions --count -1", error=True)306 307    def testWrongImage(self):308        self.expect(309            "trace load "310            + os.path.join(self.getSourceDir(), "intelpt-trace", "trace_bad_image.json")311        )312        self.expect(313            "thread trace dump instructions --forwards",314            substrs=[315                """thread #1: tid = 3842849316    ...missing instructions317    3: (error) no memory mapped at this address: 0x0000000000400511"""318            ],319        )320 321    def testWrongCPU(self):322        self.expect(323            "trace load "324            + os.path.join(self.getSourceDir(), "intelpt-trace", "trace_wrong_cpu.json")325        )326        self.expect(327            "thread trace dump instructions --forwards",328            substrs=["error: unknown cpu"],329            error=True,330        )331 332    def testMultiFileTraceWithMissingModuleInJSON(self):333        self.expect(334            "trace load "335            + os.path.join(336                self.getSourceDir(), "intelpt-trace-multi-file", "multi-file-no-ld.json"337            )338        )339 340        self.expect(341            "thread trace dump instructions --count 4 --id 9 --forwards --pretty-json",342            substrs=[343                """[344  {345    "id": 9,346    "loadAddress": "0x40054b",347    "module": "a.out",348    "symbol": "foo()",349    "mnemonic": "jmp"350  },351  {352    "id": 10,353    "loadAddress": "0x400510",354    "module": "a.out",355    "symbol": null,356    "mnemonic": "pushq"357  },358  {359    "id": 11,360    "loadAddress": "0x400516",361    "module": "a.out",362    "symbol": null,363    "mnemonic": "jmpq"364  },365  {366    "id": 12,367    "error": "no memory mapped at this address: 0x00007ffff7df1950"368  },369  {370    "id": 16,371    "loadAddress": "0x400674",372    "module": "a.out",373    "symbol": "main",374    "mnemonic": "movl",375    "source": "/home/wallace/llvm-sand/external/llvm-project/lldb/test/API/commands/trace/intelpt-trace-multi-file/main.cpp",376    "line": 10,377    "column": 0378  }379]"""380            ],381        )382 383        self.expect(384            "thread trace dump instructions --count 4 --id 20 --forwards --pretty-json",385            substrs=[386                """[387  {388    "id": 20,389    "loadAddress": "0x400677",390    "module": "a.out",391    "symbol": "main",392    "mnemonic": "movl",393    "source": "/home/wallace/llvm-sand/external/llvm-project/lldb/test/API/commands/trace/intelpt-trace-multi-file/main.cpp",394    "line": 12,395    "column": 0396  },397  {398    "id": 21,399    "loadAddress": "0x40067a",400    "module": "a.out",401    "symbol": "main",402    "mnemonic": "addl",403    "source": "/home/wallace/llvm-sand/external/llvm-project/lldb/test/API/commands/trace/intelpt-trace-multi-file/main.cpp",404    "line": 12,405    "column": 0406  },407  {408    "id": 22,409    "loadAddress": "0x40067f",410    "module": "a.out",411    "symbol": "main",412    "mnemonic": "movl",413    "source": "/home/wallace/llvm-sand/external/llvm-project/lldb/test/API/commands/trace/intelpt-trace-multi-file/main.cpp",414    "line": 12,415    "column": 0416  },417  {418    "id": 26,419    "loadAddress": "0x400682",420    "module": "a.out",421    "symbol": "inline_function()",422    "mnemonic": "movl",423    "source": "/home/wallace/llvm-sand/external/llvm-project/lldb/test/API/commands/trace/intelpt-trace-multi-file/main.cpp",424    "line": 4,425    "column": 0426  }427]"""428            ],429        )430 431    def testMultiFileTraceWithMissingModule(self):432        self.expect(433            "trace load "434            + os.path.join(435                self.getSourceDir(), "intelpt-trace-multi-file", "multi-file-no-ld.json"436            )437        )438 439        # This instructions in this test covers the following flow:440        #441        # - The trace starts with a call to libfoo, which triggers the dynamic442        #   linker, but the dynamic linker is not included in the JSON file,443        #   thus the trace reports a set of missing instructions after444        #   instruction [6].445        # - Then, the dump continues in the next synchronization point showing446        #   a call to an inlined function, which is displayed as [inlined].447        # - Finally, a call to libfoo is performed, which invokes libbar inside.448        #449        # Whenever there's a line or symbol change, including the inline case, a450        # line is printed showing the symbol context change.451        #452        # Finally, the instruction disassembly is included in the dump.453        self.expect(454            "thread trace dump instructions --count 50 --forwards",455            substrs=[456                """thread #1: tid = 815455457  a.out`main + 15 at main.cpp:10458    3: 0x000000000040066f    callq  0x400540                  ; symbol stub for: foo()459  a.out`symbol stub for: foo()460    7: 0x0000000000400540    jmpq   *0x200ae2(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 40461    8: 0x0000000000400546    pushq  $0x2462    9: 0x000000000040054b    jmp    0x400510463  a.out`(none)464    10: 0x0000000000400510    pushq  0x200af2(%rip)            ; _GLOBAL_OFFSET_TABLE_ + 8465    11: 0x0000000000400516    jmpq   *0x200af4(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 16466    ...missing instructions467    12: (error) no memory mapped at this address: 0x00007ffff7df1950468  a.out`main + 20 at main.cpp:10469    16: 0x0000000000400674    movl   %eax, -0xc(%rbp)470  a.out`main + 23 at main.cpp:12471    20: 0x0000000000400677    movl   -0xc(%rbp), %eax472    21: 0x000000000040067a    addl   $0x1, %eax473    22: 0x000000000040067f    movl   %eax, -0xc(%rbp)474  a.out`main + 34 [inlined] inline_function() at main.cpp:4475    26: 0x0000000000400682    movl   $0x0, -0x4(%rbp)476  a.out`main + 41 [inlined] inline_function() + 7 at main.cpp:5477    27: 0x0000000000400689    movl   -0x4(%rbp), %eax478    28: 0x000000000040068c    addl   $0x1, %eax479    29: 0x0000000000400691    movl   %eax, -0x4(%rbp)480  a.out`main + 52 [inlined] inline_function() + 18 at main.cpp:6481    30: 0x0000000000400694    movl   -0x4(%rbp), %eax482  a.out`main + 55 at main.cpp:14483    31: 0x0000000000400697    movl   -0xc(%rbp), %ecx484    32: 0x000000000040069a    addl   %eax, %ecx485    33: 0x000000000040069c    movl   %ecx, -0xc(%rbp)486  a.out`main + 63 at main.cpp:16487    37: 0x000000000040069f    callq  0x400540                  ; symbol stub for: foo()488  a.out`symbol stub for: foo()489    38: 0x0000000000400540    jmpq   *0x200ae2(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 40490  libfoo.so`foo() at foo.cpp:3491    39: 0x00007ffff7bd96e0    pushq  %rbp492    40: 0x00007ffff7bd96e1    movq   %rsp, %rbp493  libfoo.so`foo() + 4 at foo.cpp:4494    41: 0x00007ffff7bd96e4    subq   $0x10, %rsp495    42: 0x00007ffff7bd96e8    callq  0x7ffff7bd95d0            ; symbol stub for: bar()496  libfoo.so`symbol stub for: bar()497    43: 0x00007ffff7bd95d0    jmpq   *0x200a4a(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 32498  libbar.so`bar() at bar.cpp:1499    44: 0x00007ffff79d7690    pushq  %rbp500    45: 0x00007ffff79d7691    movq   %rsp, %rbp501  libbar.so`bar() + 4 at bar.cpp:2502    46: 0x00007ffff79d7694    movl   $0x1, -0x4(%rbp)503  libbar.so`bar() + 11 at bar.cpp:3504    47: 0x00007ffff79d769b    movl   -0x4(%rbp), %eax505    48: 0x00007ffff79d769e    addl   $0x1, %eax506    49: 0x00007ffff79d76a3    movl   %eax, -0x4(%rbp)507  libbar.so`bar() + 22 at bar.cpp:4508    50: 0x00007ffff79d76a6    movl   -0x4(%rbp), %eax509    51: 0x00007ffff79d76a9    popq   %rbp510    52: 0x00007ffff79d76aa    retq""",511                """libfoo.so`foo() + 13 at foo.cpp:4512    53: 0x00007ffff7bd96ed    movl   %eax, -0x4(%rbp)513  libfoo.so`foo() + 16 at foo.cpp:5514    54: 0x00007ffff7bd96f0    movl   -0x4(%rbp), %eax515    55: 0x00007ffff7bd96f3    addl   $0x1, %eax516    56: 0x00007ffff7bd96f8    movl   %eax, -0x4(%rbp)517  libfoo.so`foo() + 27 at foo.cpp:6518    57: 0x00007ffff7bd96fb    movl   -0x4(%rbp), %eax519    58: 0x00007ffff7bd96fe    addq   $0x10, %rsp520    59: 0x00007ffff7bd9702    popq   %rbp521    60: 0x00007ffff7bd9703    retq""",522                """a.out`main + 68 at main.cpp:16523    61: 0x00000000004006a4    movl   -0xc(%rbp), %ecx524    62: 0x00000000004006a7    addl   %eax, %ecx525    63: 0x00000000004006a9    movl   %ecx, -0xc(%rbp)526    no more data""",527            ],528        )529 530        self.expect(531            "thread trace dump instructions --count 50",532            substrs=[533                """thread #1: tid = 815455534  a.out`main + 73 at main.cpp:16535    63: 0x00000000004006a9    movl   %ecx, -0xc(%rbp)536    62: 0x00000000004006a7    addl   %eax, %ecx537    61: 0x00000000004006a4    movl   -0xc(%rbp), %ecx538  libfoo.so`foo() + 35 at foo.cpp:6539    60: 0x00007ffff7bd9703    retq""",540                """59: 0x00007ffff7bd9702    popq   %rbp541    58: 0x00007ffff7bd96fe    addq   $0x10, %rsp542    57: 0x00007ffff7bd96fb    movl   -0x4(%rbp), %eax543  libfoo.so`foo() + 24 at foo.cpp:5544    56: 0x00007ffff7bd96f8    movl   %eax, -0x4(%rbp)545    55: 0x00007ffff7bd96f3    addl   $0x1, %eax546    54: 0x00007ffff7bd96f0    movl   -0x4(%rbp), %eax547  libfoo.so`foo() + 13 at foo.cpp:4548    53: 0x00007ffff7bd96ed    movl   %eax, -0x4(%rbp)549  libbar.so`bar() + 26 at bar.cpp:4550    52: 0x00007ffff79d76aa    retq""",551                """51: 0x00007ffff79d76a9    popq   %rbp552    50: 0x00007ffff79d76a6    movl   -0x4(%rbp), %eax553  libbar.so`bar() + 19 at bar.cpp:3554    49: 0x00007ffff79d76a3    movl   %eax, -0x4(%rbp)555    48: 0x00007ffff79d769e    addl   $0x1, %eax556    47: 0x00007ffff79d769b    movl   -0x4(%rbp), %eax557  libbar.so`bar() + 4 at bar.cpp:2558    46: 0x00007ffff79d7694    movl   $0x1, -0x4(%rbp)559  libbar.so`bar() + 1 at bar.cpp:1560    45: 0x00007ffff79d7691    movq   %rsp, %rbp561    44: 0x00007ffff79d7690    pushq  %rbp562  libfoo.so`symbol stub for: bar()563    43: 0x00007ffff7bd95d0    jmpq   *0x200a4a(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 32564  libfoo.so`foo() + 8 at foo.cpp:4565    42: 0x00007ffff7bd96e8    callq  0x7ffff7bd95d0            ; symbol stub for: bar()566    41: 0x00007ffff7bd96e4    subq   $0x10, %rsp567  libfoo.so`foo() + 1 at foo.cpp:3568    40: 0x00007ffff7bd96e1    movq   %rsp, %rbp569    39: 0x00007ffff7bd96e0    pushq  %rbp570  a.out`symbol stub for: foo()571    38: 0x0000000000400540    jmpq   *0x200ae2(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 40572  a.out`main + 63 at main.cpp:16573    37: 0x000000000040069f    callq  0x400540                  ; symbol stub for: foo()574  a.out`main + 60 at main.cpp:14575    33: 0x000000000040069c    movl   %ecx, -0xc(%rbp)576    32: 0x000000000040069a    addl   %eax, %ecx577    31: 0x0000000000400697    movl   -0xc(%rbp), %ecx578  a.out`main + 52 [inlined] inline_function() + 18 at main.cpp:6579    30: 0x0000000000400694    movl   -0x4(%rbp), %eax580  a.out`main + 49 [inlined] inline_function() + 15 at main.cpp:5581    29: 0x0000000000400691    movl   %eax, -0x4(%rbp)582    28: 0x000000000040068c    addl   $0x1, %eax583    27: 0x0000000000400689    movl   -0x4(%rbp), %eax584  a.out`main + 34 [inlined] inline_function() at main.cpp:4585    26: 0x0000000000400682    movl   $0x0, -0x4(%rbp)586  a.out`main + 31 at main.cpp:12587    22: 0x000000000040067f    movl   %eax, -0xc(%rbp)588    21: 0x000000000040067a    addl   $0x1, %eax589    20: 0x0000000000400677    movl   -0xc(%rbp), %eax590  a.out`main + 20 at main.cpp:10591    16: 0x0000000000400674    movl   %eax, -0xc(%rbp)592    ...missing instructions593    12: (error) no memory mapped at this address: 0x00007ffff7df1950594  a.out`(none)595    11: 0x0000000000400516    jmpq   *0x200af4(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 16596    10: 0x0000000000400510    pushq  0x200af2(%rip)            ; _GLOBAL_OFFSET_TABLE_ + 8597  a.out`symbol stub for: foo() + 11598    9: 0x000000000040054b    jmp    0x400510599    8: 0x0000000000400546    pushq  $0x2600    7: 0x0000000000400540    jmpq   *0x200ae2(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 40601  a.out`main + 15 at main.cpp:10602    3: 0x000000000040066f    callq  0x400540                  ; symbol stub for: foo()603    no more data""",604            ],605        )606 607        self.expect(608            "thread trace dump instructions --skip 100 --forwards",609            inHistory=True,610            substrs=[611                """thread #1: tid = 815455612    no more data"""613            ],614        )615 616        self.expect(617            "",618            substrs=[619                """thread #1: tid = 815455620    no more data"""621            ],622        )623 624        self.expect(625            "thread trace dump instructions --raw --all --forwards",626            substrs=[627                """thread #1: tid = 815455628    3: 0x000000000040066f629    7: 0x0000000000400540""",630                """11: 0x0000000000400516631    ...missing instructions632    12: (error) no memory mapped at this address: 0x00007ffff7df1950633    16: 0x0000000000400674""",634                """61: 0x00000000004006a4635    62: 0x00000000004006a7636    63: 0x00000000004006a9637    no more data""",638            ],639        )640